linux/drivers/fmc/fmc-debug.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015 CERN (www.cern.ch)
   3 * Author: Federico Vaga <federico.vaga@cern.ch>
   4 *
   5 * Released according to the GNU GPL, version 2 or any later version.
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/device.h>
  10#include <linux/init.h>
  11#include <linux/fs.h>
  12#include <linux/debugfs.h>
  13#include <linux/seq_file.h>
  14#include <asm/byteorder.h>
  15
  16#include <linux/fmc.h>
  17#include <linux/sdb.h>
  18#include <linux/fmc-sdb.h>
  19
  20#define FMC_DBG_SDB_DUMP "dump_sdb"
  21
  22static char *__strip_trailing_space(char *buf, char *str, int len)
  23{
  24        int i = len - 1;
  25
  26        memcpy(buf, str, len);
  27        buf[len] = '\0';
  28        while (i >= 0 && buf[i] == ' ')
  29                buf[i--] = '\0';
  30        return buf;
  31}
  32
  33#define __sdb_string(buf, field) ({                     \
  34        BUILD_BUG_ON(sizeof(buf) < sizeof(field));      \
  35        __strip_trailing_space(buf, (void *)(field), sizeof(field));    \
  36                })
  37
  38/**
  39 * We do not check seq_printf() errors because we want to see things in any case
  40 */
  41static void fmc_sdb_dump_recursive(struct fmc_device *fmc, struct seq_file *s,
  42                                   const struct sdb_array *arr)
  43{
  44        unsigned long base = arr->baseaddr;
  45        int i, j, n = arr->len, level = arr->level;
  46        char tmp[64];
  47
  48        for (i = 0; i < n; i++) {
  49                union  sdb_record *r;
  50                struct sdb_product *p;
  51                struct sdb_component *c;
  52
  53                r = &arr->record[i];
  54                c = &r->dev.sdb_component;
  55                p = &c->product;
  56
  57                for (j = 0; j < level; j++)
  58                        seq_printf(s, "   ");
  59                switch (r->empty.record_type) {
  60                case sdb_type_interconnect:
  61                        seq_printf(s, "%08llx:%08x %.19s\n",
  62                                   __be64_to_cpu(p->vendor_id),
  63                                   __be32_to_cpu(p->device_id),
  64                                   p->name);
  65                        break;
  66                case sdb_type_device:
  67                        seq_printf(s, "%08llx:%08x %.19s (%08llx-%08llx)\n",
  68                                   __be64_to_cpu(p->vendor_id),
  69                                   __be32_to_cpu(p->device_id),
  70                                   p->name,
  71                                   __be64_to_cpu(c->addr_first) + base,
  72                                   __be64_to_cpu(c->addr_last) + base);
  73                        break;
  74                case sdb_type_bridge:
  75                        seq_printf(s, "%08llx:%08x %.19s (bridge: %08llx)\n",
  76                                   __be64_to_cpu(p->vendor_id),
  77                                   __be32_to_cpu(p->device_id),
  78                                   p->name,
  79                                   __be64_to_cpu(c->addr_first) + base);
  80                        if (IS_ERR(arr->subtree[i])) {
  81                                seq_printf(s, "SDB: (bridge error %li)\n",
  82                                         PTR_ERR(arr->subtree[i]));
  83                                break;
  84                        }
  85                        fmc_sdb_dump_recursive(fmc, s, arr->subtree[i]);
  86                        break;
  87                case sdb_type_integration:
  88                        seq_printf(s, "integration\n");
  89                        break;
  90                case sdb_type_repo_url:
  91                        seq_printf(s, "Synthesis repository: %s\n",
  92                                          __sdb_string(tmp, r->repo_url.repo_url));
  93                        break;
  94                case sdb_type_synthesis:
  95                        seq_printf(s, "Bitstream '%s' ",
  96                                          __sdb_string(tmp, r->synthesis.syn_name));
  97                        seq_printf(s, "synthesized %08x by %s ",
  98                                          __be32_to_cpu(r->synthesis.date),
  99                                          __sdb_string(tmp, r->synthesis.user_name));
 100                        seq_printf(s, "(%s version %x), ",
 101                                          __sdb_string(tmp, r->synthesis.tool_name),
 102                                          __be32_to_cpu(r->synthesis.tool_version));
 103                        seq_printf(s, "commit %pm\n",
 104                                          r->synthesis.commit_id);
 105                        break;
 106                case sdb_type_empty:
 107                        seq_printf(s, "empty\n");
 108                        break;
 109                default:
 110                        seq_printf(s, "UNKNOWN TYPE 0x%02x\n",
 111                                   r->empty.record_type);
 112                        break;
 113                }
 114        }
 115}
 116
 117static int fmc_sdb_dump(struct seq_file *s, void *offset)
 118{
 119        struct fmc_device *fmc = s->private;
 120
 121        if (!fmc->sdb) {
 122                seq_printf(s, "no SDB information\n");
 123                return 0;
 124        }
 125
 126        seq_printf(s, "FMC: %s (%s), slot %i, device %s\n", dev_name(fmc->hwdev),
 127        fmc->carrier_name, fmc->slot_id, dev_name(&fmc->dev));
 128        /* Dump SDB information */
 129        fmc_sdb_dump_recursive(fmc, s, fmc->sdb);
 130
 131        return 0;
 132}
 133
 134
 135static int fmc_sdb_dump_open(struct inode *inode, struct file *file)
 136{
 137        struct fmc_device *fmc = inode->i_private;
 138
 139        return single_open(file, fmc_sdb_dump, fmc);
 140}
 141
 142
 143const struct file_operations fmc_dbgfs_sdb_dump = {
 144        .owner = THIS_MODULE,
 145        .open  = fmc_sdb_dump_open,
 146        .read = seq_read,
 147        .llseek = seq_lseek,
 148        .release = single_release,
 149};
 150
 151int fmc_debug_init(struct fmc_device *fmc)
 152{
 153        fmc->dbg_dir = debugfs_create_dir(dev_name(&fmc->dev), NULL);
 154        if (IS_ERR_OR_NULL(fmc->dbg_dir)) {
 155                pr_err("FMC: Cannot create debugfs\n");
 156                return PTR_ERR(fmc->dbg_dir);
 157        }
 158
 159        fmc->dbg_sdb_dump = debugfs_create_file(FMC_DBG_SDB_DUMP, 0444,
 160                                                fmc->dbg_dir, fmc,
 161                                                &fmc_dbgfs_sdb_dump);
 162        if (IS_ERR_OR_NULL(fmc->dbg_sdb_dump))
 163                pr_err("FMC: Cannot create debugfs file %s\n",
 164                       FMC_DBG_SDB_DUMP);
 165
 166        return 0;
 167}
 168
 169void fmc_debug_exit(struct fmc_device *fmc)
 170{
 171        if (fmc->dbg_dir)
 172                debugfs_remove_recursive(fmc->dbg_dir);
 173}
 174