1 /** 2 * IBM Accelerator Family 'GenWQE' 3 * 4 * (C) Copyright IBM Corp. 2013 5 * 6 * Author: Frank Haverkamp <haver@linux.vnet.ibm.com> 7 * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com> 8 * Author: Michael Jung <mijung@de.ibm.com> 9 * Author: Michael Ruettger <michael@ibmra.de> 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License (version 2 only) 13 * as published by the Free Software Foundation. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 */ 20 21 /* 22 * Debugfs interfaces for the GenWQE card. Help to debug potential 23 * problems. Dump internal chip state for debugging and failure 24 * determination. 25 */ 26 27 #include <linux/module.h> 28 #include <linux/kernel.h> 29 #include <linux/init.h> 30 #include <linux/debugfs.h> 31 #include <linux/seq_file.h> 32 #include <linux/uaccess.h> 33 34 #include "card_base.h" 35 #include "card_ddcb.h" 36 37 #define GENWQE_DEBUGFS_RO(_name, _showfn) \ 38 static int genwqe_debugfs_##_name##_open(struct inode *inode, \ 39 struct file *file) \ 40 { \ 41 return single_open(file, _showfn, inode->i_private); \ 42 } \ 43 static const struct file_operations genwqe_##_name##_fops = { \ 44 .open = genwqe_debugfs_##_name##_open, \ 45 .read = seq_read, \ 46 .llseek = seq_lseek, \ 47 .release = single_release, \ 48 } 49 50 static void dbg_uidn_show(struct seq_file *s, struct genwqe_reg *regs, 51 int entries) 52 { 53 unsigned int i; 54 u32 v_hi, v_lo; 55 56 for (i = 0; i < entries; i++) { 57 v_hi = (regs[i].val >> 32) & 0xffffffff; 58 v_lo = (regs[i].val) & 0xffffffff; 59 60 seq_printf(s, " 0x%08x 0x%08x 0x%08x 0x%08x EXT_ERR_REC\n", 61 regs[i].addr, regs[i].idx, v_hi, v_lo); 62 } 63 } 64 65 static int curr_dbg_uidn_show(struct seq_file *s, void *unused, int uid) 66 { 67 struct genwqe_dev *cd = s->private; 68 int entries; 69 struct genwqe_reg *regs; 70 71 entries = genwqe_ffdc_buff_size(cd, uid); 72 if (entries < 0) 73 return -EINVAL; 74 75 if (entries == 0) 76 return 0; 77 78 regs = kcalloc(entries, sizeof(*regs), GFP_KERNEL); 79 if (regs == NULL) 80 return -ENOMEM; 81 82 genwqe_stop_traps(cd); /* halt the traps while dumping data */ 83 genwqe_ffdc_buff_read(cd, uid, regs, entries); 84 genwqe_start_traps(cd); 85 86 dbg_uidn_show(s, regs, entries); 87 kfree(regs); 88 return 0; 89 } 90 91 static int genwqe_curr_dbg_uid0_show(struct seq_file *s, void *unused) 92 { 93 return curr_dbg_uidn_show(s, unused, 0); 94 } 95 96 GENWQE_DEBUGFS_RO(curr_dbg_uid0, genwqe_curr_dbg_uid0_show); 97 98 static int genwqe_curr_dbg_uid1_show(struct seq_file *s, void *unused) 99 { 100 return curr_dbg_uidn_show(s, unused, 1); 101 } 102 103 GENWQE_DEBUGFS_RO(curr_dbg_uid1, genwqe_curr_dbg_uid1_show); 104 105 static int genwqe_curr_dbg_uid2_show(struct seq_file *s, void *unused) 106 { 107 return curr_dbg_uidn_show(s, unused, 2); 108 } 109 110 GENWQE_DEBUGFS_RO(curr_dbg_uid2, genwqe_curr_dbg_uid2_show); 111 112 static int prev_dbg_uidn_show(struct seq_file *s, void *unused, int uid) 113 { 114 struct genwqe_dev *cd = s->private; 115 116 dbg_uidn_show(s, cd->ffdc[uid].regs, cd->ffdc[uid].entries); 117 return 0; 118 } 119 120 static int genwqe_prev_dbg_uid0_show(struct seq_file *s, void *unused) 121 { 122 return prev_dbg_uidn_show(s, unused, 0); 123 } 124 125 GENWQE_DEBUGFS_RO(prev_dbg_uid0, genwqe_prev_dbg_uid0_show); 126 127 static int genwqe_prev_dbg_uid1_show(struct seq_file *s, void *unused) 128 { 129 return prev_dbg_uidn_show(s, unused, 1); 130 } 131 132 GENWQE_DEBUGFS_RO(prev_dbg_uid1, genwqe_prev_dbg_uid1_show); 133 134 static int genwqe_prev_dbg_uid2_show(struct seq_file *s, void *unused) 135 { 136 return prev_dbg_uidn_show(s, unused, 2); 137 } 138 139 GENWQE_DEBUGFS_RO(prev_dbg_uid2, genwqe_prev_dbg_uid2_show); 140 141 static int genwqe_curr_regs_show(struct seq_file *s, void *unused) 142 { 143 struct genwqe_dev *cd = s->private; 144 unsigned int i; 145 struct genwqe_reg *regs; 146 147 regs = kcalloc(GENWQE_FFDC_REGS, sizeof(*regs), GFP_KERNEL); 148 if (regs == NULL) 149 return -ENOMEM; 150 151 genwqe_stop_traps(cd); 152 genwqe_read_ffdc_regs(cd, regs, GENWQE_FFDC_REGS, 1); 153 genwqe_start_traps(cd); 154 155 for (i = 0; i < GENWQE_FFDC_REGS; i++) { 156 if (regs[i].addr == 0xffffffff) 157 break; /* invalid entries */ 158 159 if (regs[i].val == 0x0ull) 160 continue; /* do not print 0x0 FIRs */ 161 162 seq_printf(s, " 0x%08x 0x%016llx\n", 163 regs[i].addr, regs[i].val); 164 } 165 return 0; 166 } 167 168 GENWQE_DEBUGFS_RO(curr_regs, genwqe_curr_regs_show); 169 170 static int genwqe_prev_regs_show(struct seq_file *s, void *unused) 171 { 172 struct genwqe_dev *cd = s->private; 173 unsigned int i; 174 struct genwqe_reg *regs = cd->ffdc[GENWQE_DBG_REGS].regs; 175 176 if (regs == NULL) 177 return -EINVAL; 178 179 for (i = 0; i < GENWQE_FFDC_REGS; i++) { 180 if (regs[i].addr == 0xffffffff) 181 break; /* invalid entries */ 182 183 if (regs[i].val == 0x0ull) 184 continue; /* do not print 0x0 FIRs */ 185 186 seq_printf(s, " 0x%08x 0x%016llx\n", 187 regs[i].addr, regs[i].val); 188 } 189 return 0; 190 } 191 192 GENWQE_DEBUGFS_RO(prev_regs, genwqe_prev_regs_show); 193 194 static int genwqe_jtimer_show(struct seq_file *s, void *unused) 195 { 196 struct genwqe_dev *cd = s->private; 197 unsigned int vf_num; 198 u64 jtimer; 199 200 jtimer = genwqe_read_vreg(cd, IO_SLC_VF_APPJOB_TIMEOUT, 0); 201 seq_printf(s, " PF 0x%016llx %d msec\n", jtimer, 202 genwqe_pf_jobtimeout_msec); 203 204 for (vf_num = 0; vf_num < cd->num_vfs; vf_num++) { 205 jtimer = genwqe_read_vreg(cd, IO_SLC_VF_APPJOB_TIMEOUT, 206 vf_num + 1); 207 seq_printf(s, " VF%-2d 0x%016llx %d msec\n", vf_num, jtimer, 208 cd->vf_jobtimeout_msec[vf_num]); 209 } 210 return 0; 211 } 212 213 GENWQE_DEBUGFS_RO(jtimer, genwqe_jtimer_show); 214 215 static int genwqe_queue_working_time_show(struct seq_file *s, void *unused) 216 { 217 struct genwqe_dev *cd = s->private; 218 unsigned int vf_num; 219 u64 t; 220 221 t = genwqe_read_vreg(cd, IO_SLC_VF_QUEUE_WTIME, 0); 222 seq_printf(s, " PF 0x%016llx\n", t); 223 224 for (vf_num = 0; vf_num < cd->num_vfs; vf_num++) { 225 t = genwqe_read_vreg(cd, IO_SLC_VF_QUEUE_WTIME, vf_num + 1); 226 seq_printf(s, " VF%-2d 0x%016llx\n", vf_num, t); 227 } 228 return 0; 229 } 230 231 GENWQE_DEBUGFS_RO(queue_working_time, genwqe_queue_working_time_show); 232 233 static int genwqe_ddcb_info_show(struct seq_file *s, void *unused) 234 { 235 struct genwqe_dev *cd = s->private; 236 unsigned int i; 237 struct ddcb_queue *queue; 238 struct ddcb *pddcb; 239 240 queue = &cd->queue; 241 seq_puts(s, "DDCB QUEUE:\n"); 242 seq_printf(s, " ddcb_max: %d\n" 243 " ddcb_daddr: %016llx - %016llx\n" 244 " ddcb_vaddr: %016llx\n" 245 " ddcbs_in_flight: %u\n" 246 " ddcbs_max_in_flight: %u\n" 247 " ddcbs_completed: %u\n" 248 " busy: %u\n" 249 " irqs_processed: %u\n", 250 queue->ddcb_max, (long long)queue->ddcb_daddr, 251 (long long)queue->ddcb_daddr + 252 (queue->ddcb_max * DDCB_LENGTH), 253 (long long)queue->ddcb_vaddr, queue->ddcbs_in_flight, 254 queue->ddcbs_max_in_flight, queue->ddcbs_completed, 255 queue->busy, cd->irqs_processed); 256 257 /* Hardware State */ 258 seq_printf(s, " 0x%08x 0x%016llx IO_QUEUE_CONFIG\n" 259 " 0x%08x 0x%016llx IO_QUEUE_STATUS\n" 260 " 0x%08x 0x%016llx IO_QUEUE_SEGMENT\n" 261 " 0x%08x 0x%016llx IO_QUEUE_INITSQN\n" 262 " 0x%08x 0x%016llx IO_QUEUE_WRAP\n" 263 " 0x%08x 0x%016llx IO_QUEUE_OFFSET\n" 264 " 0x%08x 0x%016llx IO_QUEUE_WTIME\n" 265 " 0x%08x 0x%016llx IO_QUEUE_ERRCNTS\n" 266 " 0x%08x 0x%016llx IO_QUEUE_LRW\n", 267 queue->IO_QUEUE_CONFIG, 268 __genwqe_readq(cd, queue->IO_QUEUE_CONFIG), 269 queue->IO_QUEUE_STATUS, 270 __genwqe_readq(cd, queue->IO_QUEUE_STATUS), 271 queue->IO_QUEUE_SEGMENT, 272 __genwqe_readq(cd, queue->IO_QUEUE_SEGMENT), 273 queue->IO_QUEUE_INITSQN, 274 __genwqe_readq(cd, queue->IO_QUEUE_INITSQN), 275 queue->IO_QUEUE_WRAP, 276 __genwqe_readq(cd, queue->IO_QUEUE_WRAP), 277 queue->IO_QUEUE_OFFSET, 278 __genwqe_readq(cd, queue->IO_QUEUE_OFFSET), 279 queue->IO_QUEUE_WTIME, 280 __genwqe_readq(cd, queue->IO_QUEUE_WTIME), 281 queue->IO_QUEUE_ERRCNTS, 282 __genwqe_readq(cd, queue->IO_QUEUE_ERRCNTS), 283 queue->IO_QUEUE_LRW, 284 __genwqe_readq(cd, queue->IO_QUEUE_LRW)); 285 286 seq_printf(s, "DDCB list (ddcb_act=%d/ddcb_next=%d):\n", 287 queue->ddcb_act, queue->ddcb_next); 288 289 pddcb = queue->ddcb_vaddr; 290 for (i = 0; i < queue->ddcb_max; i++) { 291 seq_printf(s, " %-3d: RETC=%03x SEQ=%04x HSI/SHI=%02x/%02x ", 292 i, be16_to_cpu(pddcb->retc_16), 293 be16_to_cpu(pddcb->seqnum_16), 294 pddcb->hsi, pddcb->shi); 295 seq_printf(s, "PRIV=%06llx CMD=%02x\n", 296 be64_to_cpu(pddcb->priv_64), pddcb->cmd); 297 pddcb++; 298 } 299 return 0; 300 } 301 302 GENWQE_DEBUGFS_RO(ddcb_info, genwqe_ddcb_info_show); 303 304 static int genwqe_info_show(struct seq_file *s, void *unused) 305 { 306 struct genwqe_dev *cd = s->private; 307 u16 val16, type; 308 u64 app_id, slu_id, bitstream = -1; 309 struct pci_dev *pci_dev = cd->pci_dev; 310 311 slu_id = __genwqe_readq(cd, IO_SLU_UNITCFG); 312 app_id = __genwqe_readq(cd, IO_APP_UNITCFG); 313 314 if (genwqe_is_privileged(cd)) 315 bitstream = __genwqe_readq(cd, IO_SLU_BITSTREAM); 316 317 val16 = (u16)(slu_id & 0x0fLLU); 318 type = (u16)((slu_id >> 20) & 0xffLLU); 319 320 seq_printf(s, "%s driver version: %s\n" 321 " Device Name/Type: %s %s CardIdx: %d\n" 322 " SLU/APP Config : 0x%016llx/0x%016llx\n" 323 " Build Date : %u/%x/%u\n" 324 " Base Clock : %u MHz\n" 325 " Arch/SVN Release: %u/%llx\n" 326 " Bitstream : %llx\n", 327 GENWQE_DEVNAME, DRV_VERS_STRING, dev_name(&pci_dev->dev), 328 genwqe_is_privileged(cd) ? 329 "Physical" : "Virtual or no SR-IOV", 330 cd->card_idx, slu_id, app_id, 331 (u16)((slu_id >> 12) & 0x0fLLU), /* month */ 332 (u16)((slu_id >> 4) & 0xffLLU), /* day */ 333 (u16)((slu_id >> 16) & 0x0fLLU) + 2010, /* year */ 334 genwqe_base_clock_frequency(cd), 335 (u16)((slu_id >> 32) & 0xffLLU), slu_id >> 40, 336 bitstream); 337 338 return 0; 339 } 340 341 GENWQE_DEBUGFS_RO(info, genwqe_info_show); 342 343 int genwqe_init_debugfs(struct genwqe_dev *cd) 344 { 345 struct dentry *root; 346 struct dentry *file; 347 int ret; 348 char card_name[64]; 349 char name[64]; 350 unsigned int i; 351 352 sprintf(card_name, "%s%u_card", GENWQE_DEVNAME, cd->card_idx); 353 354 root = debugfs_create_dir(card_name, cd->debugfs_genwqe); 355 if (!root) { 356 ret = -ENOMEM; 357 goto err0; 358 } 359 360 /* non privileged interfaces are done here */ 361 file = debugfs_create_file("ddcb_info", S_IRUGO, root, cd, 362 &genwqe_ddcb_info_fops); 363 if (!file) { 364 ret = -ENOMEM; 365 goto err1; 366 } 367 368 file = debugfs_create_file("info", S_IRUGO, root, cd, 369 &genwqe_info_fops); 370 if (!file) { 371 ret = -ENOMEM; 372 goto err1; 373 } 374 375 file = debugfs_create_x64("err_inject", 0666, root, &cd->err_inject); 376 if (!file) { 377 ret = -ENOMEM; 378 goto err1; 379 } 380 381 file = debugfs_create_u32("ddcb_software_timeout", 0666, root, 382 &cd->ddcb_software_timeout); 383 if (!file) { 384 ret = -ENOMEM; 385 goto err1; 386 } 387 388 file = debugfs_create_u32("kill_timeout", 0666, root, 389 &cd->kill_timeout); 390 if (!file) { 391 ret = -ENOMEM; 392 goto err1; 393 } 394 395 /* privileged interfaces follow here */ 396 if (!genwqe_is_privileged(cd)) { 397 cd->debugfs_root = root; 398 return 0; 399 } 400 401 file = debugfs_create_file("curr_regs", S_IRUGO, root, cd, 402 &genwqe_curr_regs_fops); 403 if (!file) { 404 ret = -ENOMEM; 405 goto err1; 406 } 407 408 file = debugfs_create_file("curr_dbg_uid0", S_IRUGO, root, cd, 409 &genwqe_curr_dbg_uid0_fops); 410 if (!file) { 411 ret = -ENOMEM; 412 goto err1; 413 } 414 415 file = debugfs_create_file("curr_dbg_uid1", S_IRUGO, root, cd, 416 &genwqe_curr_dbg_uid1_fops); 417 if (!file) { 418 ret = -ENOMEM; 419 goto err1; 420 } 421 422 file = debugfs_create_file("curr_dbg_uid2", S_IRUGO, root, cd, 423 &genwqe_curr_dbg_uid2_fops); 424 if (!file) { 425 ret = -ENOMEM; 426 goto err1; 427 } 428 429 file = debugfs_create_file("prev_regs", S_IRUGO, root, cd, 430 &genwqe_prev_regs_fops); 431 if (!file) { 432 ret = -ENOMEM; 433 goto err1; 434 } 435 436 file = debugfs_create_file("prev_dbg_uid0", S_IRUGO, root, cd, 437 &genwqe_prev_dbg_uid0_fops); 438 if (!file) { 439 ret = -ENOMEM; 440 goto err1; 441 } 442 443 file = debugfs_create_file("prev_dbg_uid1", S_IRUGO, root, cd, 444 &genwqe_prev_dbg_uid1_fops); 445 if (!file) { 446 ret = -ENOMEM; 447 goto err1; 448 } 449 450 file = debugfs_create_file("prev_dbg_uid2", S_IRUGO, root, cd, 451 &genwqe_prev_dbg_uid2_fops); 452 if (!file) { 453 ret = -ENOMEM; 454 goto err1; 455 } 456 457 for (i = 0; i < GENWQE_MAX_VFS; i++) { 458 sprintf(name, "vf%d_jobtimeout_msec", i); 459 460 file = debugfs_create_u32(name, 0666, root, 461 &cd->vf_jobtimeout_msec[i]); 462 if (!file) { 463 ret = -ENOMEM; 464 goto err1; 465 } 466 } 467 468 file = debugfs_create_file("jobtimer", S_IRUGO, root, cd, 469 &genwqe_jtimer_fops); 470 if (!file) { 471 ret = -ENOMEM; 472 goto err1; 473 } 474 475 file = debugfs_create_file("queue_working_time", S_IRUGO, root, cd, 476 &genwqe_queue_working_time_fops); 477 if (!file) { 478 ret = -ENOMEM; 479 goto err1; 480 } 481 482 file = debugfs_create_u32("skip_recovery", 0666, root, 483 &cd->skip_recovery); 484 if (!file) { 485 ret = -ENOMEM; 486 goto err1; 487 } 488 489 cd->debugfs_root = root; 490 return 0; 491 err1: 492 debugfs_remove_recursive(root); 493 err0: 494 return ret; 495 } 496 497 void genqwe_exit_debugfs(struct genwqe_dev *cd) 498 { 499 debugfs_remove_recursive(cd->debugfs_root); 500 } 501