Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/drivers/misc/genwqe/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 10 kB image not shown  

Quelle  card_debugfs.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * IBM Accelerator Family 'GenWQE'
 *
 * (C) Copyright IBM Corp. 2013
 *
 * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
 * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
 * Author: Michael Jung <mijung@gmx.net>
 * Author: Michael Ruettger <michael@ibmra.de>
 */


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


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>

#include "card_base.h"
#include "card_ddcb.h"

static void dbg_uidn_show(struct seq_file *s, struct genwqe_reg *regs,
     int entries)
{
 unsigned int i;
 u32 v_hi, v_lo;

 for (i = 0; i < entries; i++) {
  v_hi = (regs[i].val >> 32) & 0xffffffff;
  v_lo = (regs[i].val)       & 0xffffffff;

  seq_printf(s, " 0x%08x 0x%08x 0x%08x 0x%08x EXT_ERR_REC\n",
      regs[i].addr, regs[i].idx, v_hi, v_lo);
 }
}

static int curr_dbg_uidn_show(struct seq_file *s, void *unused, int uid)
{
 struct genwqe_dev *cd = s->private;
 int entries;
 struct genwqe_reg *regs;

 entries = genwqe_ffdc_buff_size(cd, uid);
 if (entries < 0)
  return -EINVAL;

 if (entries == 0)
  return 0;

 regs = kcalloc(entries, sizeof(*regs), GFP_KERNEL);
 if (regs == NULL)
  return -ENOMEM;

 genwqe_stop_traps(cd); /* halt the traps while dumping data */
 genwqe_ffdc_buff_read(cd, uid, regs, entries);
 genwqe_start_traps(cd);

 dbg_uidn_show(s, regs, entries);
 kfree(regs);
 return 0;
}

static int curr_dbg_uid0_show(struct seq_file *s, void *unused)
{
 return curr_dbg_uidn_show(s, unused, 0);
}

DEFINE_SHOW_ATTRIBUTE(curr_dbg_uid0);

static int curr_dbg_uid1_show(struct seq_file *s, void *unused)
{
 return curr_dbg_uidn_show(s, unused, 1);
}

DEFINE_SHOW_ATTRIBUTE(curr_dbg_uid1);

static int curr_dbg_uid2_show(struct seq_file *s, void *unused)
{
 return curr_dbg_uidn_show(s, unused, 2);
}

DEFINE_SHOW_ATTRIBUTE(curr_dbg_uid2);

static int prev_dbg_uidn_show(struct seq_file *s, void *unused, int uid)
{
 struct genwqe_dev *cd = s->private;

 dbg_uidn_show(s, cd->ffdc[uid].regs,  cd->ffdc[uid].entries);
 return 0;
}

static int prev_dbg_uid0_show(struct seq_file *s, void *unused)
{
 return prev_dbg_uidn_show(s, unused, 0);
}

DEFINE_SHOW_ATTRIBUTE(prev_dbg_uid0);

static int prev_dbg_uid1_show(struct seq_file *s, void *unused)
{
 return prev_dbg_uidn_show(s, unused, 1);
}

DEFINE_SHOW_ATTRIBUTE(prev_dbg_uid1);

static int prev_dbg_uid2_show(struct seq_file *s, void *unused)
{
 return prev_dbg_uidn_show(s, unused, 2);
}

DEFINE_SHOW_ATTRIBUTE(prev_dbg_uid2);

static int curr_regs_show(struct seq_file *s, void *unused)
{
 struct genwqe_dev *cd = s->private;
 unsigned int i;
 struct genwqe_reg *regs;

 regs = kcalloc(GENWQE_FFDC_REGS, sizeof(*regs), GFP_KERNEL);
 if (regs == NULL)
  return -ENOMEM;

 genwqe_stop_traps(cd);
 genwqe_read_ffdc_regs(cd, regs, GENWQE_FFDC_REGS, 1);
 genwqe_start_traps(cd);

 for (i = 0; i < GENWQE_FFDC_REGS; i++) {
  if (regs[i].addr == 0xffffffff)
   break;  /* invalid entries */

  if (regs[i].val == 0x0ull)
   continue;  /* do not print 0x0 FIRs */

  seq_printf(s, " 0x%08x 0x%016llx\n",
      regs[i].addr, regs[i].val);
 }
 return 0;
}

DEFINE_SHOW_ATTRIBUTE(curr_regs);

static int prev_regs_show(struct seq_file *s, void *unused)
{
 struct genwqe_dev *cd = s->private;
 unsigned int i;
 struct genwqe_reg *regs = cd->ffdc[GENWQE_DBG_REGS].regs;

 if (regs == NULL)
  return -EINVAL;

 for (i = 0; i < GENWQE_FFDC_REGS; i++) {
  if (regs[i].addr == 0xffffffff)
   break;  /* invalid entries */

  if (regs[i].val == 0x0ull)
   continue;  /* do not print 0x0 FIRs */

  seq_printf(s, " 0x%08x 0x%016llx\n",
      regs[i].addr, regs[i].val);
 }
 return 0;
}

DEFINE_SHOW_ATTRIBUTE(prev_regs);

static int jtimer_show(struct seq_file *s, void *unused)
{
 struct genwqe_dev *cd = s->private;
 unsigned int vf_num;
 u64 jtimer;

 jtimer = genwqe_read_vreg(cd, IO_SLC_VF_APPJOB_TIMEOUT, 0);
 seq_printf(s, " PF 0x%016llx %d msec\n", jtimer,
     GENWQE_PF_JOBTIMEOUT_MSEC);

 for (vf_num = 0; vf_num < cd->num_vfs; vf_num++) {
  jtimer = genwqe_read_vreg(cd, IO_SLC_VF_APPJOB_TIMEOUT,
       vf_num + 1);
  seq_printf(s, " VF%-2d 0x%016llx %d msec\n", vf_num, jtimer,
      cd->vf_jobtimeout_msec[vf_num]);
 }
 return 0;
}

DEFINE_SHOW_ATTRIBUTE(jtimer);

static int queue_working_time_show(struct seq_file *s, void *unused)
{
 struct genwqe_dev *cd = s->private;
 unsigned int vf_num;
 u64 t;

 t = genwqe_read_vreg(cd, IO_SLC_VF_QUEUE_WTIME, 0);
 seq_printf(s, " PF 0x%016llx\n", t);

 for (vf_num = 0; vf_num < cd->num_vfs; vf_num++) {
  t = genwqe_read_vreg(cd, IO_SLC_VF_QUEUE_WTIME, vf_num + 1);
  seq_printf(s, " VF%-2d 0x%016llx\n", vf_num, t);
 }
 return 0;
}

DEFINE_SHOW_ATTRIBUTE(queue_working_time);

static int ddcb_info_show(struct seq_file *s, void *unused)
{
 struct genwqe_dev *cd = s->private;
 unsigned int i;
 struct ddcb_queue *queue;
 struct ddcb *pddcb;

 queue = &cd->queue;
 seq_puts(s, "DDCB QUEUE:\n");
 seq_printf(s, " ddcb_max: %d\n"
     " ddcb_daddr: %016llx - %016llx\n"
     " ddcb_vaddr: %p\n"
     " ddcbs_in_flight: %u\n"
     " ddcbs_max_in_flight: %u\n"
     " ddcbs_completed: %u\n"
     " return_on_busy: %u\n"
     " wait_on_busy: %u\n"
     " irqs_processed: %u\n",
     queue->ddcb_max, (long long)queue->ddcb_daddr,
     (long long)queue->ddcb_daddr +
     (queue->ddcb_max * DDCB_LENGTH),
     queue->ddcb_vaddr, queue->ddcbs_in_flight,
     queue->ddcbs_max_in_flight, queue->ddcbs_completed,
     queue->return_on_busy, queue->wait_on_busy,
     cd->irqs_processed);

 /* Hardware State */
 seq_printf(s, " 0x%08x 0x%016llx IO_QUEUE_CONFIG\n"
     " 0x%08x 0x%016llx IO_QUEUE_STATUS\n"
     " 0x%08x 0x%016llx IO_QUEUE_SEGMENT\n"
     " 0x%08x 0x%016llx IO_QUEUE_INITSQN\n"
     " 0x%08x 0x%016llx IO_QUEUE_WRAP\n"
     " 0x%08x 0x%016llx IO_QUEUE_OFFSET\n"
     " 0x%08x 0x%016llx IO_QUEUE_WTIME\n"
     " 0x%08x 0x%016llx IO_QUEUE_ERRCNTS\n"
     " 0x%08x 0x%016llx IO_QUEUE_LRW\n",
     queue->IO_QUEUE_CONFIG,
     __genwqe_readq(cd, queue->IO_QUEUE_CONFIG),
     queue->IO_QUEUE_STATUS,
     __genwqe_readq(cd, queue->IO_QUEUE_STATUS),
     queue->IO_QUEUE_SEGMENT,
     __genwqe_readq(cd, queue->IO_QUEUE_SEGMENT),
     queue->IO_QUEUE_INITSQN,
     __genwqe_readq(cd, queue->IO_QUEUE_INITSQN),
     queue->IO_QUEUE_WRAP,
     __genwqe_readq(cd, queue->IO_QUEUE_WRAP),
     queue->IO_QUEUE_OFFSET,
     __genwqe_readq(cd, queue->IO_QUEUE_OFFSET),
     queue->IO_QUEUE_WTIME,
     __genwqe_readq(cd, queue->IO_QUEUE_WTIME),
     queue->IO_QUEUE_ERRCNTS,
     __genwqe_readq(cd, queue->IO_QUEUE_ERRCNTS),
     queue->IO_QUEUE_LRW,
     __genwqe_readq(cd, queue->IO_QUEUE_LRW));

 seq_printf(s, "DDCB list (ddcb_act=%d/ddcb_next=%d):\n",
     queue->ddcb_act, queue->ddcb_next);

 pddcb = queue->ddcb_vaddr;
 for (i = 0; i < queue->ddcb_max; i++) {
  seq_printf(s, " %-3d: RETC=%03x SEQ=%04x HSI/SHI=%02x/%02x ",
      i, be16_to_cpu(pddcb->retc_16),
      be16_to_cpu(pddcb->seqnum_16),
      pddcb->hsi, pddcb->shi);
  seq_printf(s, "PRIV=%06llx CMD=%02x\n",
      be64_to_cpu(pddcb->priv_64), pddcb->cmd);
  pddcb++;
 }
 return 0;
}

DEFINE_SHOW_ATTRIBUTE(ddcb_info);

static int info_show(struct seq_file *s, void *unused)
{
 struct genwqe_dev *cd = s->private;
 u64 app_id, slu_id, bitstream = -1;
 struct pci_dev *pci_dev = cd->pci_dev;

 slu_id = __genwqe_readq(cd, IO_SLU_UNITCFG);
 app_id = __genwqe_readq(cd, IO_APP_UNITCFG);

 if (genwqe_is_privileged(cd))
  bitstream = __genwqe_readq(cd, IO_SLU_BITSTREAM);

 seq_printf(s, "%s driver version: %s\n"
     " Device Name/Type: %s %s CardIdx: %d\n"
     " SLU/APP Config : 0x%016llx/0x%016llx\n"
     " Build Date : %u/%x/%u\n"
     " Base Clock : %u MHz\n"
     " Arch/SVN Release: %u/%llx\n"
     " Bitstream : %llx\n",
     GENWQE_DEVNAME, DRV_VERSION, dev_name(&pci_dev->dev),
     genwqe_is_privileged(cd) ?
     "Physical" : "Virtual or no SR-IOV",
     cd->card_idx, slu_id, app_id,
     (u16)((slu_id >> 12) & 0x0fLLU),    /* month */
     (u16)((slu_id >>  4) & 0xffLLU),    /* day */
     (u16)((slu_id >> 16) & 0x0fLLU) + 2010, /* year */
     genwqe_base_clock_frequency(cd),
     (u16)((slu_id >> 32) & 0xffLLU), slu_id >> 40,
     bitstream);

 return 0;
}

DEFINE_SHOW_ATTRIBUTE(info);

void genwqe_init_debugfs(struct genwqe_dev *cd)
{
 struct dentry *root;
 char card_name[64];
 char name[64];
 unsigned int i;

 sprintf(card_name, "%s%d_card", GENWQE_DEVNAME, cd->card_idx);

 root = debugfs_create_dir(card_name, cd->debugfs_genwqe);

 /* non privileged interfaces are done here */
 debugfs_create_file("ddcb_info", S_IRUGO, root, cd, &ddcb_info_fops);
 debugfs_create_file("info", S_IRUGO, root, cd, &info_fops);
 debugfs_create_x64("err_inject", 0666, root, &cd->err_inject);
 debugfs_create_u32("ddcb_software_timeout", 0666, root,
      &cd->ddcb_software_timeout);
 debugfs_create_u32("kill_timeout", 0666, root, &cd->kill_timeout);

 /* privileged interfaces follow here */
 if (!genwqe_is_privileged(cd)) {
  cd->debugfs_root = root;
  return;
 }

 debugfs_create_file("curr_regs", S_IRUGO, root, cd, &curr_regs_fops);
 debugfs_create_file("curr_dbg_uid0", S_IRUGO, root, cd,
       &curr_dbg_uid0_fops);
 debugfs_create_file("curr_dbg_uid1", S_IRUGO, root, cd,
       &curr_dbg_uid1_fops);
 debugfs_create_file("curr_dbg_uid2", S_IRUGO, root, cd,
       &curr_dbg_uid2_fops);
 debugfs_create_file("prev_regs", S_IRUGO, root, cd, &prev_regs_fops);
 debugfs_create_file("prev_dbg_uid0", S_IRUGO, root, cd,
       &prev_dbg_uid0_fops);
 debugfs_create_file("prev_dbg_uid1", S_IRUGO, root, cd,
       &prev_dbg_uid1_fops);
 debugfs_create_file("prev_dbg_uid2", S_IRUGO, root, cd,
       &prev_dbg_uid2_fops);

 for (i = 0; i <  GENWQE_MAX_VFS; i++) {
  sprintf(name, "vf%u_jobtimeout_msec", i);
  debugfs_create_u32(name, 0666, root,
       &cd->vf_jobtimeout_msec[i]);
 }

 debugfs_create_file("jobtimer", S_IRUGO, root, cd, &jtimer_fops);
 debugfs_create_file("queue_working_time", S_IRUGO, root, cd,
       &queue_working_time_fops);
 debugfs_create_u32("skip_recovery", 0666, root, &cd->skip_recovery);
 debugfs_create_u32("use_platform_recovery", 0666, root,
      &cd->use_platform_recovery);

 cd->debugfs_root = root;
}

void genqwe_exit_debugfs(struct genwqe_dev *cd)
{
 debugfs_remove_recursive(cd->debugfs_root);
}

Messung V0.5
C=95 H=94 G=94

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.