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

GenWQE Debugfs interfaces

Debugfs interfaces for the GenWQE card. Help to debug potential
problems. Dump internal chip state for debugging and failure
determination.

Signed-off-by: Frank Haverkamp <haver@linux.vnet.ibm.com>
Co-authors: Joerg-Stephan Vogt <jsvogt@de.ibm.com>,
Michael Jung <MIJUNG@de.ibm.com>,
Michael Ruettger <michael@ibmra.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Frank Haverkamp and committed by
Greg Kroah-Hartman
c59330cd 67f4addb

+591
+91
Documentation/ABI/testing/debugfs-driver-genwqe
··· 1 + What: /sys/kernel/debug/genwqe/genwqe<n>_card/ddcb_info 2 + Date: Oct 2013 3 + Contact: haver@linux.vnet.ibm.com 4 + Description: DDCB queue dump used for debugging queueing problems. 5 + 6 + What: /sys/kernel/debug/genwqe/genwqe<n>_card/curr_regs 7 + Date: Oct 2013 8 + Contact: haver@linux.vnet.ibm.com 9 + Description: Dump of the current error registers. 10 + Only available for PF. 11 + 12 + What: /sys/kernel/debug/genwqe/genwqe<n>_card/curr_dbg_uid0 13 + Date: Oct 2013 14 + Contact: haver@linux.vnet.ibm.com 15 + Description: Internal chip state of UID0 (unit id 0). 16 + Only available for PF. 17 + 18 + What: /sys/kernel/debug/genwqe/genwqe<n>_card/curr_dbg_uid1 19 + Date: Oct 2013 20 + Contact: haver@linux.vnet.ibm.com 21 + Description: Internal chip state of UID1. 22 + Only available for PF. 23 + 24 + What: /sys/kernel/debug/genwqe/genwqe<n>_card/curr_dbg_uid2 25 + Date: Oct 2013 26 + Contact: haver@linux.vnet.ibm.com 27 + Description: Internal chip state of UID2. 28 + Only available for PF. 29 + 30 + What: /sys/kernel/debug/genwqe/genwqe<n>_card/prev_regs 31 + Date: Oct 2013 32 + Contact: haver@linux.vnet.ibm.com 33 + Description: Dump of the error registers before the last reset of 34 + the card occured. 35 + Only available for PF. 36 + 37 + What: /sys/kernel/debug/genwqe/genwqe<n>_card/prev_dbg_uid0 38 + Date: Oct 2013 39 + Contact: haver@linux.vnet.ibm.com 40 + Description: Internal chip state of UID0 before card was reset. 41 + Only available for PF. 42 + 43 + What: /sys/kernel/debug/genwqe/genwqe<n>_card/prev_dbg_uid1 44 + Date: Oct 2013 45 + Contact: haver@linux.vnet.ibm.com 46 + Description: Internal chip state of UID1 before card was reset. 47 + Only available for PF. 48 + 49 + What: /sys/kernel/debug/genwqe/genwqe<n>_card/prev_dbg_uid2 50 + Date: Oct 2013 51 + Contact: haver@linux.vnet.ibm.com 52 + Description: Internal chip state of UID2 before card was reset. 53 + Only available for PF. 54 + 55 + What: /sys/kernel/debug/genwqe/genwqe<n>_card/info 56 + Date: Oct 2013 57 + Contact: haver@linux.vnet.ibm.com 58 + Description: Comprehensive summary of bitstream version and software 59 + version. Used bitstream and bitstream clocking information. 60 + 61 + What: /sys/kernel/debug/genwqe/genwqe<n>_card/err_inject 62 + Date: Oct 2013 63 + Contact: haver@linux.vnet.ibm.com 64 + Description: Possibility to inject error cases to ensure that the drivers 65 + error handling code works well. 66 + 67 + What: /sys/kernel/debug/genwqe/genwqe<n>_card/vf<0..14>_jobtimeout_msec 68 + Date: Oct 2013 69 + Contact: haver@linux.vnet.ibm.com 70 + Description: Default VF timeout 250ms. Testing might require 1000ms. 71 + Using 0 will use the cards default value (whatever that is). 72 + 73 + The timeout depends on the max number of available cards 74 + in the system and the maximum allowed queue size. 75 + 76 + The driver ensures that the settings are done just before 77 + the VFs get enabled. Changing the timeouts in flight is not 78 + possible. 79 + Only available for PF. 80 + 81 + What: /sys/kernel/debug/genwqe/genwqe<n>_card/jobtimer 82 + Date: Oct 2013 83 + Contact: haver@linux.vnet.ibm.com 84 + Description: Dump job timeout register values for PF and VFs. 85 + Only available for PF. 86 + 87 + What: /sys/kernel/debug/genwqe/genwqe<n>_card/queue_working_time 88 + Date: Dec 2013 89 + Contact: haver@linux.vnet.ibm.com 90 + Description: Dump queue working time register values for PF and VFs. 91 + Only available for PF.
+500
drivers/misc/genwqe/card_debugfs.c
··· 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 + }