linux/drivers/fmc/fmc-dump.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2013 CERN (www.cern.ch)
   3 * Author: Alessandro Rubini <rubini@gnudd.com>
   4 *
   5 * Released according to the GNU GPL, version 2 or any later version.
   6 *
   7 * This work is part of the White Rabbit project, a research effort led
   8 * by CERN, the European Institute for Nuclear Research.
   9 */
  10#include <linux/kernel.h>
  11#include <linux/moduleparam.h>
  12#include <linux/device.h>
  13#include <linux/fmc.h>
  14#include <linux/fmc-sdb.h>
  15
  16static int fmc_must_dump_eeprom;
  17module_param_named(dump_eeprom, fmc_must_dump_eeprom, int, 0644);
  18static int fmc_must_dump_sdb;
  19module_param_named(dump_sdb, fmc_must_dump_sdb, int, 0644);
  20
  21#define LINELEN 16
  22
  23/* Dumping 8k takes oh so much: avoid duplicate lines */
  24static const uint8_t *dump_line(int addr, const uint8_t *line,
  25                                const uint8_t *prev)
  26{
  27        int i;
  28
  29        if (!prev || memcmp(line, prev, LINELEN)) {
  30                pr_info("%04x: ", addr);
  31                for (i = 0; i < LINELEN; ) {
  32                        printk(KERN_CONT "%02x", line[i]);
  33                        i++;
  34                        printk(i & 3 ? " " : i & (LINELEN - 1) ? "  " : "\n");
  35                }
  36                return line;
  37        }
  38        /* repeated line */
  39        if (line == prev + LINELEN)
  40                pr_info("[...]\n");
  41        return prev;
  42}
  43
  44void fmc_dump_eeprom(const struct fmc_device *fmc)
  45{
  46        const uint8_t *line, *prev;
  47        int i;
  48
  49        if (!fmc_must_dump_eeprom)
  50                return;
  51
  52        pr_info("FMC: %s (%s), slot %i, device %s\n", dev_name(fmc->hwdev),
  53                fmc->carrier_name, fmc->slot_id, dev_name(&fmc->dev));
  54        pr_info("FMC: dumping eeprom 0x%x (%i) bytes\n", fmc->eeprom_len,
  55               fmc->eeprom_len);
  56
  57        line = fmc->eeprom;
  58        prev = NULL;
  59        for (i = 0; i < fmc->eeprom_len; i += LINELEN, line += LINELEN)
  60                prev = dump_line(i, line, prev);
  61}
  62
  63void fmc_dump_sdb(const struct fmc_device *fmc)
  64{
  65        const uint8_t *line, *prev;
  66        int i, len;
  67
  68        if (!fmc->sdb)
  69                return;
  70        if (!fmc_must_dump_sdb)
  71                return;
  72
  73        /* If the argument is not-zero, do simple dump (== show) */
  74        if (fmc_must_dump_sdb > 0)
  75                fmc_show_sdb_tree(fmc);
  76
  77        if (fmc_must_dump_sdb == 1)
  78                return;
  79
  80        /* If bigger than 1, dump it seriously, to help debugging */
  81
  82        /*
  83         * Here we should really use libsdbfs (which is designed to
  84         * work in kernel space as well) , but it doesn't support
  85         * directories yet, and it requires better intergration (it
  86         * should be used instead of fmc-specific code).
  87         *
  88         * So, lazily, just dump the top-level array
  89         */
  90        pr_info("FMC: %s (%s), slot %i, device %s\n", dev_name(fmc->hwdev),
  91                fmc->carrier_name, fmc->slot_id, dev_name(&fmc->dev));
  92        pr_info("FMC: poor dump of sdb first level:\n");
  93
  94        len = fmc->sdb->len * sizeof(union sdb_record);
  95        line = (void *)fmc->sdb->record;
  96        prev = NULL;
  97        for (i = 0; i < len; i += LINELEN, line += LINELEN)
  98                prev = dump_line(i, line, prev);
  99        return;
 100}
 101