Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * IBM Accelerator Family 'GenWQE'
0004  *
0005  * (C) Copyright IBM Corp. 2013
0006  *
0007  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
0008  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
0009  * Author: Michael Jung <mijung@gmx.net>
0010  * Author: Michael Ruettger <michael@ibmra.de>
0011  */
0012 
0013 /*
0014  * Debugfs interfaces for the GenWQE card. Help to debug potential
0015  * problems. Dump internal chip state for debugging and failure
0016  * determination.
0017  */
0018 
0019 #include <linux/module.h>
0020 #include <linux/kernel.h>
0021 #include <linux/debugfs.h>
0022 #include <linux/seq_file.h>
0023 #include <linux/uaccess.h>
0024 
0025 #include "card_base.h"
0026 #include "card_ddcb.h"
0027 
0028 static void dbg_uidn_show(struct seq_file *s, struct genwqe_reg *regs,
0029               int entries)
0030 {
0031     unsigned int i;
0032     u32 v_hi, v_lo;
0033 
0034     for (i = 0; i < entries; i++) {
0035         v_hi = (regs[i].val >> 32) & 0xffffffff;
0036         v_lo = (regs[i].val)       & 0xffffffff;
0037 
0038         seq_printf(s, "  0x%08x 0x%08x 0x%08x 0x%08x EXT_ERR_REC\n",
0039                regs[i].addr, regs[i].idx, v_hi, v_lo);
0040     }
0041 }
0042 
0043 static int curr_dbg_uidn_show(struct seq_file *s, void *unused, int uid)
0044 {
0045     struct genwqe_dev *cd = s->private;
0046     int entries;
0047     struct genwqe_reg *regs;
0048 
0049     entries = genwqe_ffdc_buff_size(cd, uid);
0050     if (entries < 0)
0051         return -EINVAL;
0052 
0053     if (entries == 0)
0054         return 0;
0055 
0056     regs = kcalloc(entries, sizeof(*regs), GFP_KERNEL);
0057     if (regs == NULL)
0058         return -ENOMEM;
0059 
0060     genwqe_stop_traps(cd); /* halt the traps while dumping data */
0061     genwqe_ffdc_buff_read(cd, uid, regs, entries);
0062     genwqe_start_traps(cd);
0063 
0064     dbg_uidn_show(s, regs, entries);
0065     kfree(regs);
0066     return 0;
0067 }
0068 
0069 static int curr_dbg_uid0_show(struct seq_file *s, void *unused)
0070 {
0071     return curr_dbg_uidn_show(s, unused, 0);
0072 }
0073 
0074 DEFINE_SHOW_ATTRIBUTE(curr_dbg_uid0);
0075 
0076 static int curr_dbg_uid1_show(struct seq_file *s, void *unused)
0077 {
0078     return curr_dbg_uidn_show(s, unused, 1);
0079 }
0080 
0081 DEFINE_SHOW_ATTRIBUTE(curr_dbg_uid1);
0082 
0083 static int curr_dbg_uid2_show(struct seq_file *s, void *unused)
0084 {
0085     return curr_dbg_uidn_show(s, unused, 2);
0086 }
0087 
0088 DEFINE_SHOW_ATTRIBUTE(curr_dbg_uid2);
0089 
0090 static int prev_dbg_uidn_show(struct seq_file *s, void *unused, int uid)
0091 {
0092     struct genwqe_dev *cd = s->private;
0093 
0094     dbg_uidn_show(s, cd->ffdc[uid].regs,  cd->ffdc[uid].entries);
0095     return 0;
0096 }
0097 
0098 static int prev_dbg_uid0_show(struct seq_file *s, void *unused)
0099 {
0100     return prev_dbg_uidn_show(s, unused, 0);
0101 }
0102 
0103 DEFINE_SHOW_ATTRIBUTE(prev_dbg_uid0);
0104 
0105 static int prev_dbg_uid1_show(struct seq_file *s, void *unused)
0106 {
0107     return prev_dbg_uidn_show(s, unused, 1);
0108 }
0109 
0110 DEFINE_SHOW_ATTRIBUTE(prev_dbg_uid1);
0111 
0112 static int prev_dbg_uid2_show(struct seq_file *s, void *unused)
0113 {
0114     return prev_dbg_uidn_show(s, unused, 2);
0115 }
0116 
0117 DEFINE_SHOW_ATTRIBUTE(prev_dbg_uid2);
0118 
0119 static int curr_regs_show(struct seq_file *s, void *unused)
0120 {
0121     struct genwqe_dev *cd = s->private;
0122     unsigned int i;
0123     struct genwqe_reg *regs;
0124 
0125     regs = kcalloc(GENWQE_FFDC_REGS, sizeof(*regs), GFP_KERNEL);
0126     if (regs == NULL)
0127         return -ENOMEM;
0128 
0129     genwqe_stop_traps(cd);
0130     genwqe_read_ffdc_regs(cd, regs, GENWQE_FFDC_REGS, 1);
0131     genwqe_start_traps(cd);
0132 
0133     for (i = 0; i < GENWQE_FFDC_REGS; i++) {
0134         if (regs[i].addr == 0xffffffff)
0135             break;  /* invalid entries */
0136 
0137         if (regs[i].val == 0x0ull)
0138             continue;  /* do not print 0x0 FIRs */
0139 
0140         seq_printf(s, "  0x%08x 0x%016llx\n",
0141                regs[i].addr, regs[i].val);
0142     }
0143     return 0;
0144 }
0145 
0146 DEFINE_SHOW_ATTRIBUTE(curr_regs);
0147 
0148 static int prev_regs_show(struct seq_file *s, void *unused)
0149 {
0150     struct genwqe_dev *cd = s->private;
0151     unsigned int i;
0152     struct genwqe_reg *regs = cd->ffdc[GENWQE_DBG_REGS].regs;
0153 
0154     if (regs == NULL)
0155         return -EINVAL;
0156 
0157     for (i = 0; i < GENWQE_FFDC_REGS; i++) {
0158         if (regs[i].addr == 0xffffffff)
0159             break;  /* invalid entries */
0160 
0161         if (regs[i].val == 0x0ull)
0162             continue;  /* do not print 0x0 FIRs */
0163 
0164         seq_printf(s, "  0x%08x 0x%016llx\n",
0165                regs[i].addr, regs[i].val);
0166     }
0167     return 0;
0168 }
0169 
0170 DEFINE_SHOW_ATTRIBUTE(prev_regs);
0171 
0172 static int jtimer_show(struct seq_file *s, void *unused)
0173 {
0174     struct genwqe_dev *cd = s->private;
0175     unsigned int vf_num;
0176     u64 jtimer;
0177 
0178     jtimer = genwqe_read_vreg(cd, IO_SLC_VF_APPJOB_TIMEOUT, 0);
0179     seq_printf(s, "  PF   0x%016llx %d msec\n", jtimer,
0180            GENWQE_PF_JOBTIMEOUT_MSEC);
0181 
0182     for (vf_num = 0; vf_num < cd->num_vfs; vf_num++) {
0183         jtimer = genwqe_read_vreg(cd, IO_SLC_VF_APPJOB_TIMEOUT,
0184                       vf_num + 1);
0185         seq_printf(s, "  VF%-2d 0x%016llx %d msec\n", vf_num, jtimer,
0186                cd->vf_jobtimeout_msec[vf_num]);
0187     }
0188     return 0;
0189 }
0190 
0191 DEFINE_SHOW_ATTRIBUTE(jtimer);
0192 
0193 static int queue_working_time_show(struct seq_file *s, void *unused)
0194 {
0195     struct genwqe_dev *cd = s->private;
0196     unsigned int vf_num;
0197     u64 t;
0198 
0199     t = genwqe_read_vreg(cd, IO_SLC_VF_QUEUE_WTIME, 0);
0200     seq_printf(s, "  PF   0x%016llx\n", t);
0201 
0202     for (vf_num = 0; vf_num < cd->num_vfs; vf_num++) {
0203         t = genwqe_read_vreg(cd, IO_SLC_VF_QUEUE_WTIME, vf_num + 1);
0204         seq_printf(s, "  VF%-2d 0x%016llx\n", vf_num, t);
0205     }
0206     return 0;
0207 }
0208 
0209 DEFINE_SHOW_ATTRIBUTE(queue_working_time);
0210 
0211 static int ddcb_info_show(struct seq_file *s, void *unused)
0212 {
0213     struct genwqe_dev *cd = s->private;
0214     unsigned int i;
0215     struct ddcb_queue *queue;
0216     struct ddcb *pddcb;
0217 
0218     queue = &cd->queue;
0219     seq_puts(s, "DDCB QUEUE:\n");
0220     seq_printf(s, "  ddcb_max:            %d\n"
0221            "  ddcb_daddr:          %016llx - %016llx\n"
0222            "  ddcb_vaddr:          %p\n"
0223            "  ddcbs_in_flight:     %u\n"
0224            "  ddcbs_max_in_flight: %u\n"
0225            "  ddcbs_completed:     %u\n"
0226            "  return_on_busy:      %u\n"
0227            "  wait_on_busy:        %u\n"
0228            "  irqs_processed:      %u\n",
0229            queue->ddcb_max, (long long)queue->ddcb_daddr,
0230            (long long)queue->ddcb_daddr +
0231            (queue->ddcb_max * DDCB_LENGTH),
0232            queue->ddcb_vaddr, queue->ddcbs_in_flight,
0233            queue->ddcbs_max_in_flight, queue->ddcbs_completed,
0234            queue->return_on_busy, queue->wait_on_busy,
0235            cd->irqs_processed);
0236 
0237     /* Hardware State */
0238     seq_printf(s, "  0x%08x 0x%016llx IO_QUEUE_CONFIG\n"
0239            "  0x%08x 0x%016llx IO_QUEUE_STATUS\n"
0240            "  0x%08x 0x%016llx IO_QUEUE_SEGMENT\n"
0241            "  0x%08x 0x%016llx IO_QUEUE_INITSQN\n"
0242            "  0x%08x 0x%016llx IO_QUEUE_WRAP\n"
0243            "  0x%08x 0x%016llx IO_QUEUE_OFFSET\n"
0244            "  0x%08x 0x%016llx IO_QUEUE_WTIME\n"
0245            "  0x%08x 0x%016llx IO_QUEUE_ERRCNTS\n"
0246            "  0x%08x 0x%016llx IO_QUEUE_LRW\n",
0247            queue->IO_QUEUE_CONFIG,
0248            __genwqe_readq(cd, queue->IO_QUEUE_CONFIG),
0249            queue->IO_QUEUE_STATUS,
0250            __genwqe_readq(cd, queue->IO_QUEUE_STATUS),
0251            queue->IO_QUEUE_SEGMENT,
0252            __genwqe_readq(cd, queue->IO_QUEUE_SEGMENT),
0253            queue->IO_QUEUE_INITSQN,
0254            __genwqe_readq(cd, queue->IO_QUEUE_INITSQN),
0255            queue->IO_QUEUE_WRAP,
0256            __genwqe_readq(cd, queue->IO_QUEUE_WRAP),
0257            queue->IO_QUEUE_OFFSET,
0258            __genwqe_readq(cd, queue->IO_QUEUE_OFFSET),
0259            queue->IO_QUEUE_WTIME,
0260            __genwqe_readq(cd, queue->IO_QUEUE_WTIME),
0261            queue->IO_QUEUE_ERRCNTS,
0262            __genwqe_readq(cd, queue->IO_QUEUE_ERRCNTS),
0263            queue->IO_QUEUE_LRW,
0264            __genwqe_readq(cd, queue->IO_QUEUE_LRW));
0265 
0266     seq_printf(s, "DDCB list (ddcb_act=%d/ddcb_next=%d):\n",
0267            queue->ddcb_act, queue->ddcb_next);
0268 
0269     pddcb = queue->ddcb_vaddr;
0270     for (i = 0; i < queue->ddcb_max; i++) {
0271         seq_printf(s, "  %-3d: RETC=%03x SEQ=%04x HSI/SHI=%02x/%02x ",
0272                i, be16_to_cpu(pddcb->retc_16),
0273                be16_to_cpu(pddcb->seqnum_16),
0274                pddcb->hsi, pddcb->shi);
0275         seq_printf(s, "PRIV=%06llx CMD=%02x\n",
0276                be64_to_cpu(pddcb->priv_64), pddcb->cmd);
0277         pddcb++;
0278     }
0279     return 0;
0280 }
0281 
0282 DEFINE_SHOW_ATTRIBUTE(ddcb_info);
0283 
0284 static int info_show(struct seq_file *s, void *unused)
0285 {
0286     struct genwqe_dev *cd = s->private;
0287     u64 app_id, slu_id, bitstream = -1;
0288     struct pci_dev *pci_dev = cd->pci_dev;
0289 
0290     slu_id = __genwqe_readq(cd, IO_SLU_UNITCFG);
0291     app_id = __genwqe_readq(cd, IO_APP_UNITCFG);
0292 
0293     if (genwqe_is_privileged(cd))
0294         bitstream = __genwqe_readq(cd, IO_SLU_BITSTREAM);
0295 
0296     seq_printf(s, "%s driver version: %s\n"
0297            "    Device Name/Type: %s %s CardIdx: %d\n"
0298            "    SLU/APP Config  : 0x%016llx/0x%016llx\n"
0299            "    Build Date      : %u/%x/%u\n"
0300            "    Base Clock      : %u MHz\n"
0301            "    Arch/SVN Release: %u/%llx\n"
0302            "    Bitstream       : %llx\n",
0303            GENWQE_DEVNAME, DRV_VERSION, dev_name(&pci_dev->dev),
0304            genwqe_is_privileged(cd) ?
0305            "Physical" : "Virtual or no SR-IOV",
0306            cd->card_idx, slu_id, app_id,
0307            (u16)((slu_id >> 12) & 0x0fLLU),    /* month */
0308            (u16)((slu_id >>  4) & 0xffLLU),    /* day */
0309            (u16)((slu_id >> 16) & 0x0fLLU) + 2010, /* year */
0310            genwqe_base_clock_frequency(cd),
0311            (u16)((slu_id >> 32) & 0xffLLU), slu_id >> 40,
0312            bitstream);
0313 
0314     return 0;
0315 }
0316 
0317 DEFINE_SHOW_ATTRIBUTE(info);
0318 
0319 void genwqe_init_debugfs(struct genwqe_dev *cd)
0320 {
0321     struct dentry *root;
0322     char card_name[64];
0323     char name[64];
0324     unsigned int i;
0325 
0326     sprintf(card_name, "%s%d_card", GENWQE_DEVNAME, cd->card_idx);
0327 
0328     root = debugfs_create_dir(card_name, cd->debugfs_genwqe);
0329 
0330     /* non privileged interfaces are done here */
0331     debugfs_create_file("ddcb_info", S_IRUGO, root, cd, &ddcb_info_fops);
0332     debugfs_create_file("info", S_IRUGO, root, cd, &info_fops);
0333     debugfs_create_x64("err_inject", 0666, root, &cd->err_inject);
0334     debugfs_create_u32("ddcb_software_timeout", 0666, root,
0335                &cd->ddcb_software_timeout);
0336     debugfs_create_u32("kill_timeout", 0666, root, &cd->kill_timeout);
0337 
0338     /* privileged interfaces follow here */
0339     if (!genwqe_is_privileged(cd)) {
0340         cd->debugfs_root = root;
0341         return;
0342     }
0343 
0344     debugfs_create_file("curr_regs", S_IRUGO, root, cd, &curr_regs_fops);
0345     debugfs_create_file("curr_dbg_uid0", S_IRUGO, root, cd,
0346                 &curr_dbg_uid0_fops);
0347     debugfs_create_file("curr_dbg_uid1", S_IRUGO, root, cd,
0348                 &curr_dbg_uid1_fops);
0349     debugfs_create_file("curr_dbg_uid2", S_IRUGO, root, cd,
0350                 &curr_dbg_uid2_fops);
0351     debugfs_create_file("prev_regs", S_IRUGO, root, cd, &prev_regs_fops);
0352     debugfs_create_file("prev_dbg_uid0", S_IRUGO, root, cd,
0353                 &prev_dbg_uid0_fops);
0354     debugfs_create_file("prev_dbg_uid1", S_IRUGO, root, cd,
0355                 &prev_dbg_uid1_fops);
0356     debugfs_create_file("prev_dbg_uid2", S_IRUGO, root, cd,
0357                 &prev_dbg_uid2_fops);
0358 
0359     for (i = 0; i <  GENWQE_MAX_VFS; i++) {
0360         sprintf(name, "vf%u_jobtimeout_msec", i);
0361         debugfs_create_u32(name, 0666, root,
0362                    &cd->vf_jobtimeout_msec[i]);
0363     }
0364 
0365     debugfs_create_file("jobtimer", S_IRUGO, root, cd, &jtimer_fops);
0366     debugfs_create_file("queue_working_time", S_IRUGO, root, cd,
0367                 &queue_working_time_fops);
0368     debugfs_create_u32("skip_recovery", 0666, root, &cd->skip_recovery);
0369     debugfs_create_u32("use_platform_recovery", 0666, root,
0370                &cd->use_platform_recovery);
0371 
0372     cd->debugfs_root = root;
0373 }
0374 
0375 void genqwe_exit_debugfs(struct genwqe_dev *cd)
0376 {
0377     debugfs_remove_recursive(cd->debugfs_root);
0378 }