linux/drivers/misc/mic/host/mic_debugfs.c
<<
>>
Prefs
   1/*
   2 * Intel MIC Platform Software Stack (MPSS)
   3 *
   4 * Copyright(c) 2013 Intel Corporation.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License, version 2, as
   8 * published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful, but
  11 * WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13 * General Public License for more details.
  14 *
  15 * The full GNU General Public License is included in this distribution in
  16 * the file called "COPYING".
  17 *
  18 * Intel MIC Host driver.
  19 *
  20 */
  21#include <linux/debugfs.h>
  22#include <linux/pci.h>
  23#include <linux/seq_file.h>
  24
  25#include <linux/mic_common.h>
  26#include "../common/mic_dev.h"
  27#include "mic_device.h"
  28#include "mic_smpt.h"
  29#include "mic_virtio.h"
  30
  31/* Debugfs parent dir */
  32static struct dentry *mic_dbg;
  33
  34static int mic_smpt_show(struct seq_file *s, void *pos)
  35{
  36        int i;
  37        struct mic_device *mdev = s->private;
  38        unsigned long flags;
  39
  40        seq_printf(s, "MIC %-2d |%-10s| %-14s %-10s\n",
  41                   mdev->id, "SMPT entry", "SW DMA addr", "RefCount");
  42        seq_puts(s, "====================================================\n");
  43
  44        if (mdev->smpt) {
  45                struct mic_smpt_info *smpt_info = mdev->smpt;
  46                spin_lock_irqsave(&smpt_info->smpt_lock, flags);
  47                for (i = 0; i < smpt_info->info.num_reg; i++) {
  48                        seq_printf(s, "%9s|%-10d| %-#14llx %-10lld\n",
  49                                   " ",  i, smpt_info->entry[i].dma_addr,
  50                                   smpt_info->entry[i].ref_count);
  51                }
  52                spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
  53        }
  54        seq_puts(s, "====================================================\n");
  55        return 0;
  56}
  57
  58static int mic_smpt_debug_open(struct inode *inode, struct file *file)
  59{
  60        return single_open(file, mic_smpt_show, inode->i_private);
  61}
  62
  63static int mic_smpt_debug_release(struct inode *inode, struct file *file)
  64{
  65        return single_release(inode, file);
  66}
  67
  68static const struct file_operations smpt_file_ops = {
  69        .owner   = THIS_MODULE,
  70        .open    = mic_smpt_debug_open,
  71        .read    = seq_read,
  72        .llseek  = seq_lseek,
  73        .release = mic_smpt_debug_release
  74};
  75
  76static int mic_post_code_show(struct seq_file *s, void *pos)
  77{
  78        struct mic_device *mdev = s->private;
  79        u32 reg = mdev->ops->get_postcode(mdev);
  80
  81        seq_printf(s, "%c%c", reg & 0xff, (reg >> 8) & 0xff);
  82        return 0;
  83}
  84
  85static int mic_post_code_debug_open(struct inode *inode, struct file *file)
  86{
  87        return single_open(file, mic_post_code_show, inode->i_private);
  88}
  89
  90static int mic_post_code_debug_release(struct inode *inode, struct file *file)
  91{
  92        return single_release(inode, file);
  93}
  94
  95static const struct file_operations post_code_ops = {
  96        .owner   = THIS_MODULE,
  97        .open    = mic_post_code_debug_open,
  98        .read    = seq_read,
  99        .llseek  = seq_lseek,
 100        .release = mic_post_code_debug_release
 101};
 102
 103static int mic_dp_show(struct seq_file *s, void *pos)
 104{
 105        struct mic_device *mdev = s->private;
 106        struct mic_device_desc *d;
 107        struct mic_device_ctrl *dc;
 108        struct mic_vqconfig *vqconfig;
 109        __u32 *features;
 110        __u8 *config;
 111        struct mic_bootparam *bootparam = mdev->dp;
 112        int i, j;
 113
 114        seq_printf(s, "Bootparam: magic 0x%x\n",
 115                   bootparam->magic);
 116        seq_printf(s, "Bootparam: h2c_config_db %d\n",
 117                   bootparam->h2c_config_db);
 118        seq_printf(s, "Bootparam: node_id %d\n",
 119                   bootparam->node_id);
 120        seq_printf(s, "Bootparam: c2h_scif_db %d\n",
 121                   bootparam->c2h_scif_db);
 122        seq_printf(s, "Bootparam: h2c_scif_db %d\n",
 123                   bootparam->h2c_scif_db);
 124        seq_printf(s, "Bootparam: scif_host_dma_addr 0x%llx\n",
 125                   bootparam->scif_host_dma_addr);
 126        seq_printf(s, "Bootparam: scif_card_dma_addr 0x%llx\n",
 127                   bootparam->scif_card_dma_addr);
 128
 129
 130        for (i = sizeof(*bootparam); i < MIC_DP_SIZE;
 131             i += mic_total_desc_size(d)) {
 132                d = mdev->dp + i;
 133                dc = (void *)d + mic_aligned_desc_size(d);
 134
 135                /* end of list */
 136                if (d->type == 0)
 137                        break;
 138
 139                if (d->type == -1)
 140                        continue;
 141
 142                seq_printf(s, "Type %d ", d->type);
 143                seq_printf(s, "Num VQ %d ", d->num_vq);
 144                seq_printf(s, "Feature Len %d\n", d->feature_len);
 145                seq_printf(s, "Config Len %d ", d->config_len);
 146                seq_printf(s, "Shutdown Status %d\n", d->status);
 147
 148                for (j = 0; j < d->num_vq; j++) {
 149                        vqconfig = mic_vq_config(d) + j;
 150                        seq_printf(s, "vqconfig[%d]: ", j);
 151                        seq_printf(s, "address 0x%llx ", vqconfig->address);
 152                        seq_printf(s, "num %d ", vqconfig->num);
 153                        seq_printf(s, "used address 0x%llx\n",
 154                                   vqconfig->used_address);
 155                }
 156
 157                features = (__u32 *)mic_vq_features(d);
 158                seq_printf(s, "Features: Host 0x%x ", features[0]);
 159                seq_printf(s, "Guest 0x%x\n", features[1]);
 160
 161                config = mic_vq_configspace(d);
 162                for (j = 0; j < d->config_len; j++)
 163                        seq_printf(s, "config[%d]=%d\n", j, config[j]);
 164
 165                seq_puts(s, "Device control:\n");
 166                seq_printf(s, "Config Change %d ", dc->config_change);
 167                seq_printf(s, "Vdev reset %d\n", dc->vdev_reset);
 168                seq_printf(s, "Guest Ack %d ", dc->guest_ack);
 169                seq_printf(s, "Host ack %d\n", dc->host_ack);
 170                seq_printf(s, "Used address updated %d ",
 171                           dc->used_address_updated);
 172                seq_printf(s, "Vdev 0x%llx\n", dc->vdev);
 173                seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db);
 174                seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db);
 175        }
 176
 177        return 0;
 178}
 179
 180static int mic_dp_debug_open(struct inode *inode, struct file *file)
 181{
 182        return single_open(file, mic_dp_show, inode->i_private);
 183}
 184
 185static int mic_dp_debug_release(struct inode *inode, struct file *file)
 186{
 187        return single_release(inode, file);
 188}
 189
 190static const struct file_operations dp_ops = {
 191        .owner   = THIS_MODULE,
 192        .open    = mic_dp_debug_open,
 193        .read    = seq_read,
 194        .llseek  = seq_lseek,
 195        .release = mic_dp_debug_release
 196};
 197
 198static int mic_vdev_info_show(struct seq_file *s, void *unused)
 199{
 200        struct mic_device *mdev = s->private;
 201        struct list_head *pos, *tmp;
 202        struct mic_vdev *mvdev;
 203        int i, j;
 204
 205        mutex_lock(&mdev->mic_mutex);
 206        list_for_each_safe(pos, tmp, &mdev->vdev_list) {
 207                mvdev = list_entry(pos, struct mic_vdev, list);
 208                seq_printf(s, "VDEV type %d state %s in %ld out %ld\n",
 209                           mvdev->virtio_id,
 210                           mic_vdevup(mvdev) ? "UP" : "DOWN",
 211                           mvdev->in_bytes,
 212                           mvdev->out_bytes);
 213                for (i = 0; i < MIC_MAX_VRINGS; i++) {
 214                        struct vring_desc *desc;
 215                        struct vring_avail *avail;
 216                        struct vring_used *used;
 217                        struct mic_vringh *mvr = &mvdev->mvr[i];
 218                        struct vringh *vrh = &mvr->vrh;
 219                        int num = vrh->vring.num;
 220                        if (!num)
 221                                continue;
 222                        desc = vrh->vring.desc;
 223                        seq_printf(s, "vring i %d avail_idx %d",
 224                                   i, mvr->vring.info->avail_idx & (num - 1));
 225                        seq_printf(s, " vring i %d avail_idx %d\n",
 226                                   i, mvr->vring.info->avail_idx);
 227                        seq_printf(s, "vrh i %d weak_barriers %d",
 228                                   i, vrh->weak_barriers);
 229                        seq_printf(s, " last_avail_idx %d last_used_idx %d",
 230                                   vrh->last_avail_idx, vrh->last_used_idx);
 231                        seq_printf(s, " completed %d\n", vrh->completed);
 232                        for (j = 0; j < num; j++) {
 233                                seq_printf(s, "desc[%d] addr 0x%llx len %d",
 234                                           j, desc->addr, desc->len);
 235                                seq_printf(s, " flags 0x%x next %d\n",
 236                                           desc->flags, desc->next);
 237                                desc++;
 238                        }
 239                        avail = vrh->vring.avail;
 240                        seq_printf(s, "avail flags 0x%x idx %d\n",
 241                                   vringh16_to_cpu(vrh, avail->flags),
 242                                   vringh16_to_cpu(vrh, avail->idx) & (num - 1));
 243                        seq_printf(s, "avail flags 0x%x idx %d\n",
 244                                   vringh16_to_cpu(vrh, avail->flags),
 245                                   vringh16_to_cpu(vrh, avail->idx));
 246                        for (j = 0; j < num; j++)
 247                                seq_printf(s, "avail ring[%d] %d\n",
 248                                           j, avail->ring[j]);
 249                        used = vrh->vring.used;
 250                        seq_printf(s, "used flags 0x%x idx %d\n",
 251                                   vringh16_to_cpu(vrh, used->flags),
 252                                   vringh16_to_cpu(vrh, used->idx) & (num - 1));
 253                        seq_printf(s, "used flags 0x%x idx %d\n",
 254                                   vringh16_to_cpu(vrh, used->flags),
 255                                   vringh16_to_cpu(vrh, used->idx));
 256                        for (j = 0; j < num; j++)
 257                                seq_printf(s, "used ring[%d] id %d len %d\n",
 258                                           j, vringh32_to_cpu(vrh,
 259                                                              used->ring[j].id),
 260                                           vringh32_to_cpu(vrh,
 261                                                           used->ring[j].len));
 262                }
 263        }
 264        mutex_unlock(&mdev->mic_mutex);
 265
 266        return 0;
 267}
 268
 269static int mic_vdev_info_debug_open(struct inode *inode, struct file *file)
 270{
 271        return single_open(file, mic_vdev_info_show, inode->i_private);
 272}
 273
 274static int mic_vdev_info_debug_release(struct inode *inode, struct file *file)
 275{
 276        return single_release(inode, file);
 277}
 278
 279static const struct file_operations vdev_info_ops = {
 280        .owner   = THIS_MODULE,
 281        .open    = mic_vdev_info_debug_open,
 282        .read    = seq_read,
 283        .llseek  = seq_lseek,
 284        .release = mic_vdev_info_debug_release
 285};
 286
 287static int mic_msi_irq_info_show(struct seq_file *s, void *pos)
 288{
 289        struct mic_device *mdev  = s->private;
 290        int reg;
 291        int i, j;
 292        u16 entry;
 293        u16 vector;
 294        struct pci_dev *pdev = mdev->pdev;
 295
 296        if (pci_dev_msi_enabled(pdev)) {
 297                for (i = 0; i < mdev->irq_info.num_vectors; i++) {
 298                        if (pdev->msix_enabled) {
 299                                entry = mdev->irq_info.msix_entries[i].entry;
 300                                vector = mdev->irq_info.msix_entries[i].vector;
 301                        } else {
 302                                entry = 0;
 303                                vector = pdev->irq;
 304                        }
 305
 306                        reg = mdev->intr_ops->read_msi_to_src_map(mdev, entry);
 307
 308                        seq_printf(s, "%s %-10d %s %-10d MXAR[%d]: %08X\n",
 309                                   "IRQ:", vector, "Entry:", entry, i, reg);
 310
 311                        seq_printf(s, "%-10s", "offset:");
 312                        for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--)
 313                                seq_printf(s, "%4d ", j);
 314                        seq_puts(s, "\n");
 315
 316
 317                        seq_printf(s, "%-10s", "count:");
 318                        for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--)
 319                                seq_printf(s, "%4d ",
 320                                           (mdev->irq_info.mic_msi_map[i] &
 321                                           BIT(j)) ? 1 : 0);
 322                        seq_puts(s, "\n\n");
 323                }
 324        } else {
 325                seq_puts(s, "MSI/MSIx interrupts not enabled\n");
 326        }
 327
 328        return 0;
 329}
 330
 331static int mic_msi_irq_info_debug_open(struct inode *inode, struct file *file)
 332{
 333        return single_open(file, mic_msi_irq_info_show, inode->i_private);
 334}
 335
 336static int
 337mic_msi_irq_info_debug_release(struct inode *inode, struct file *file)
 338{
 339        return single_release(inode, file);
 340}
 341
 342static const struct file_operations msi_irq_info_ops = {
 343        .owner   = THIS_MODULE,
 344        .open    = mic_msi_irq_info_debug_open,
 345        .read    = seq_read,
 346        .llseek  = seq_lseek,
 347        .release = mic_msi_irq_info_debug_release
 348};
 349
 350/**
 351 * mic_create_debug_dir - Initialize MIC debugfs entries.
 352 */
 353void mic_create_debug_dir(struct mic_device *mdev)
 354{
 355        char name[16];
 356
 357        if (!mic_dbg)
 358                return;
 359
 360        scnprintf(name, sizeof(name), "mic%d", mdev->id);
 361        mdev->dbg_dir = debugfs_create_dir(name, mic_dbg);
 362        if (!mdev->dbg_dir)
 363                return;
 364
 365        debugfs_create_file("smpt", 0444, mdev->dbg_dir, mdev, &smpt_file_ops);
 366
 367        debugfs_create_file("post_code", 0444, mdev->dbg_dir, mdev,
 368                            &post_code_ops);
 369
 370        debugfs_create_file("dp", 0444, mdev->dbg_dir, mdev, &dp_ops);
 371
 372        debugfs_create_file("vdev_info", 0444, mdev->dbg_dir, mdev,
 373                            &vdev_info_ops);
 374
 375        debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir, mdev,
 376                            &msi_irq_info_ops);
 377}
 378
 379/**
 380 * mic_delete_debug_dir - Uninitialize MIC debugfs entries.
 381 */
 382void mic_delete_debug_dir(struct mic_device *mdev)
 383{
 384        if (!mdev->dbg_dir)
 385                return;
 386
 387        debugfs_remove_recursive(mdev->dbg_dir);
 388}
 389
 390/**
 391 * mic_init_debugfs - Initialize global debugfs entry.
 392 */
 393void __init mic_init_debugfs(void)
 394{
 395        mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
 396        if (!mic_dbg)
 397                pr_err("can't create debugfs dir\n");
 398}
 399
 400/**
 401 * mic_exit_debugfs - Uninitialize global debugfs entry
 402 */
 403void mic_exit_debugfs(void)
 404{
 405        debugfs_remove(mic_dbg);
 406}
 407