linux/arch/s390/pci/pci_debug.c
<<
>>
Prefs
   1/*
   2 *  Copyright IBM Corp. 2012,2015
   3 *
   4 *  Author(s):
   5 *    Jan Glauber <jang@linux.vnet.ibm.com>
   6 */
   7
   8#define KMSG_COMPONENT "zpci"
   9#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  10
  11#include <linux/kernel.h>
  12#include <linux/seq_file.h>
  13#include <linux/debugfs.h>
  14#include <linux/export.h>
  15#include <linux/pci.h>
  16#include <asm/debug.h>
  17
  18#include <asm/pci_dma.h>
  19
  20static struct dentry *debugfs_root;
  21debug_info_t *pci_debug_msg_id;
  22EXPORT_SYMBOL_GPL(pci_debug_msg_id);
  23debug_info_t *pci_debug_err_id;
  24EXPORT_SYMBOL_GPL(pci_debug_err_id);
  25
  26static char *pci_common_names[] = {
  27        "Load operations",
  28        "Store operations",
  29        "Store block operations",
  30        "Refresh operations",
  31};
  32
  33static char *pci_fmt0_names[] = {
  34        "DMA read bytes",
  35        "DMA write bytes",
  36};
  37
  38static char *pci_fmt1_names[] = {
  39        "Received bytes",
  40        "Received packets",
  41        "Transmitted bytes",
  42        "Transmitted packets",
  43};
  44
  45static char *pci_fmt2_names[] = {
  46        "Consumed work units",
  47        "Maximum work units",
  48};
  49
  50static char *pci_sw_names[] = {
  51        "Allocated pages",
  52        "Mapped pages",
  53        "Unmapped pages",
  54};
  55
  56static void pci_fmb_show(struct seq_file *m, char *name[], int length,
  57                         u64 *data)
  58{
  59        int i;
  60
  61        for (i = 0; i < length; i++, data++)
  62                seq_printf(m, "%26s:\t%llu\n", name[i], *data);
  63}
  64
  65static void pci_sw_counter_show(struct seq_file *m)
  66{
  67        struct zpci_dev *zdev = m->private;
  68        atomic64_t *counter = &zdev->allocated_pages;
  69        int i;
  70
  71        for (i = 0; i < ARRAY_SIZE(pci_sw_names); i++, counter++)
  72                seq_printf(m, "%26s:\t%lu\n", pci_sw_names[i],
  73                           atomic64_read(counter));
  74}
  75
  76static int pci_perf_show(struct seq_file *m, void *v)
  77{
  78        struct zpci_dev *zdev = m->private;
  79
  80        if (!zdev)
  81                return 0;
  82
  83        mutex_lock(&zdev->lock);
  84        if (!zdev->fmb) {
  85                mutex_unlock(&zdev->lock);
  86                seq_puts(m, "FMB statistics disabled\n");
  87                return 0;
  88        }
  89
  90        /* header */
  91        seq_printf(m, "FMB @ %p\n", zdev->fmb);
  92        seq_printf(m, "Update interval: %u ms\n", zdev->fmb_update);
  93        seq_printf(m, "Samples: %u\n", zdev->fmb->samples);
  94        seq_printf(m, "Last update TOD: %Lx\n", zdev->fmb->last_update);
  95
  96        pci_fmb_show(m, pci_common_names, ARRAY_SIZE(pci_common_names),
  97                     &zdev->fmb->ld_ops);
  98
  99        switch (zdev->fmb->format) {
 100        case 0:
 101                if (!(zdev->fmb->fmt_ind & ZPCI_FMB_DMA_COUNTER_VALID))
 102                        break;
 103                pci_fmb_show(m, pci_fmt0_names, ARRAY_SIZE(pci_fmt0_names),
 104                             &zdev->fmb->fmt0.dma_rbytes);
 105                break;
 106        case 1:
 107                pci_fmb_show(m, pci_fmt1_names, ARRAY_SIZE(pci_fmt1_names),
 108                             &zdev->fmb->fmt1.rx_bytes);
 109                break;
 110        case 2:
 111                pci_fmb_show(m, pci_fmt2_names, ARRAY_SIZE(pci_fmt2_names),
 112                             &zdev->fmb->fmt2.consumed_work_units);
 113                break;
 114        default:
 115                seq_puts(m, "Unknown format\n");
 116        }
 117
 118        pci_sw_counter_show(m);
 119        mutex_unlock(&zdev->lock);
 120        return 0;
 121}
 122
 123static ssize_t pci_perf_seq_write(struct file *file, const char __user *ubuf,
 124                                  size_t count, loff_t *off)
 125{
 126        struct zpci_dev *zdev = ((struct seq_file *) file->private_data)->private;
 127        unsigned long val;
 128        int rc;
 129
 130        if (!zdev)
 131                return 0;
 132
 133        rc = kstrtoul_from_user(ubuf, count, 10, &val);
 134        if (rc)
 135                return rc;
 136
 137        mutex_lock(&zdev->lock);
 138        switch (val) {
 139        case 0:
 140                rc = zpci_fmb_disable_device(zdev);
 141                break;
 142        case 1:
 143                rc = zpci_fmb_enable_device(zdev);
 144                break;
 145        }
 146        mutex_unlock(&zdev->lock);
 147        return rc ? rc : count;
 148}
 149
 150static int pci_perf_seq_open(struct inode *inode, struct file *filp)
 151{
 152        return single_open(filp, pci_perf_show,
 153                           file_inode(filp)->i_private);
 154}
 155
 156static const struct file_operations debugfs_pci_perf_fops = {
 157        .open    = pci_perf_seq_open,
 158        .read    = seq_read,
 159        .write   = pci_perf_seq_write,
 160        .llseek  = seq_lseek,
 161        .release = single_release,
 162};
 163
 164void zpci_debug_init_device(struct zpci_dev *zdev, const char *name)
 165{
 166        zdev->debugfs_dev = debugfs_create_dir(name, debugfs_root);
 167        if (IS_ERR(zdev->debugfs_dev))
 168                zdev->debugfs_dev = NULL;
 169
 170        zdev->debugfs_perf = debugfs_create_file("statistics",
 171                                S_IFREG | S_IRUGO | S_IWUSR,
 172                                zdev->debugfs_dev, zdev,
 173                                &debugfs_pci_perf_fops);
 174        if (IS_ERR(zdev->debugfs_perf))
 175                zdev->debugfs_perf = NULL;
 176}
 177
 178void zpci_debug_exit_device(struct zpci_dev *zdev)
 179{
 180        debugfs_remove(zdev->debugfs_perf);
 181        debugfs_remove(zdev->debugfs_dev);
 182}
 183
 184int __init zpci_debug_init(void)
 185{
 186        /* event trace buffer */
 187        pci_debug_msg_id = debug_register("pci_msg", 8, 1, 8 * sizeof(long));
 188        if (!pci_debug_msg_id)
 189                return -EINVAL;
 190        debug_register_view(pci_debug_msg_id, &debug_sprintf_view);
 191        debug_set_level(pci_debug_msg_id, 3);
 192
 193        /* error log */
 194        pci_debug_err_id = debug_register("pci_error", 2, 1, 16);
 195        if (!pci_debug_err_id)
 196                return -EINVAL;
 197        debug_register_view(pci_debug_err_id, &debug_hex_ascii_view);
 198        debug_set_level(pci_debug_err_id, 6);
 199
 200        debugfs_root = debugfs_create_dir("pci", NULL);
 201        return 0;
 202}
 203
 204void zpci_debug_exit(void)
 205{
 206        debug_unregister(pci_debug_msg_id);
 207        debug_unregister(pci_debug_err_id);
 208        debugfs_remove(debugfs_root);
 209}
 210