linux/drivers/scsi/qedf/qedf_debugfs.c
<<
>>
Prefs
   1/*
   2 *  QLogic FCoE Offload Driver
   3 *  Copyright (c) 2016-2018 QLogic Corporation
   4 *
   5 *  This software is available under the terms of the GNU General Public License
   6 *  (GPL) Version 2, available from the file COPYING in the main directory of
   7 *  this source tree.
   8 */
   9#ifdef CONFIG_DEBUG_FS
  10
  11#include <linux/uaccess.h>
  12#include <linux/debugfs.h>
  13#include <linux/module.h>
  14
  15#include "qedf.h"
  16#include "qedf_dbg.h"
  17
  18static struct dentry *qedf_dbg_root;
  19
  20/**
  21 * qedf_dbg_host_init - setup the debugfs file for the pf
  22 * @pf: the pf that is starting up
  23 **/
  24void
  25qedf_dbg_host_init(struct qedf_dbg_ctx *qedf,
  26                    const struct qedf_debugfs_ops *dops,
  27                    const struct file_operations *fops)
  28{
  29        char host_dirname[32];
  30        struct dentry *file_dentry = NULL;
  31
  32        QEDF_INFO(qedf, QEDF_LOG_DEBUGFS, "Creating debugfs host node\n");
  33        /* create pf dir */
  34        sprintf(host_dirname, "host%u", qedf->host_no);
  35        qedf->bdf_dentry = debugfs_create_dir(host_dirname, qedf_dbg_root);
  36        if (!qedf->bdf_dentry)
  37                return;
  38
  39        /* create debugfs files */
  40        while (dops) {
  41                if (!(dops->name))
  42                        break;
  43
  44                file_dentry = debugfs_create_file(dops->name, 0600,
  45                                                  qedf->bdf_dentry, qedf,
  46                                                  fops);
  47                if (!file_dentry) {
  48                        QEDF_INFO(qedf, QEDF_LOG_DEBUGFS,
  49                                   "Debugfs entry %s creation failed\n",
  50                                   dops->name);
  51                        debugfs_remove_recursive(qedf->bdf_dentry);
  52                        return;
  53                }
  54                dops++;
  55                fops++;
  56        }
  57}
  58
  59/**
  60 * qedf_dbg_host_exit - clear out the pf's debugfs entries
  61 * @pf: the pf that is stopping
  62 **/
  63void
  64qedf_dbg_host_exit(struct qedf_dbg_ctx *qedf)
  65{
  66        QEDF_INFO(qedf, QEDF_LOG_DEBUGFS, "Destroying debugfs host "
  67                   "entry\n");
  68        /* remove debugfs  entries of this PF */
  69        debugfs_remove_recursive(qedf->bdf_dentry);
  70        qedf->bdf_dentry = NULL;
  71}
  72
  73/**
  74 * qedf_dbg_init - start up debugfs for the driver
  75 **/
  76void
  77qedf_dbg_init(char *drv_name)
  78{
  79        QEDF_INFO(NULL, QEDF_LOG_DEBUGFS, "Creating debugfs root node\n");
  80
  81        /* create qed dir in root of debugfs. NULL means debugfs root */
  82        qedf_dbg_root = debugfs_create_dir(drv_name, NULL);
  83        if (!qedf_dbg_root)
  84                QEDF_INFO(NULL, QEDF_LOG_DEBUGFS, "Init of debugfs "
  85                           "failed\n");
  86}
  87
  88/**
  89 * qedf_dbg_exit - clean out the driver's debugfs entries
  90 **/
  91void
  92qedf_dbg_exit(void)
  93{
  94        QEDF_INFO(NULL, QEDF_LOG_DEBUGFS, "Destroying debugfs root "
  95                   "entry\n");
  96
  97        /* remove qed dir in root of debugfs */
  98        debugfs_remove_recursive(qedf_dbg_root);
  99        qedf_dbg_root = NULL;
 100}
 101
 102const struct qedf_debugfs_ops qedf_debugfs_ops[] = {
 103        { "fp_int", NULL },
 104        { "io_trace", NULL },
 105        { "debug", NULL },
 106        { "stop_io_on_error", NULL},
 107        { "driver_stats", NULL},
 108        { "clear_stats", NULL},
 109        { "offload_stats", NULL},
 110        /* This must be last */
 111        { NULL, NULL }
 112};
 113
 114DECLARE_PER_CPU(struct qedf_percpu_iothread_s, qedf_percpu_iothreads);
 115
 116static ssize_t
 117qedf_dbg_fp_int_cmd_read(struct file *filp, char __user *buffer, size_t count,
 118                         loff_t *ppos)
 119{
 120        size_t cnt = 0;
 121        int id;
 122        struct qedf_fastpath *fp = NULL;
 123        struct qedf_dbg_ctx *qedf_dbg =
 124                                (struct qedf_dbg_ctx *)filp->private_data;
 125        struct qedf_ctx *qedf = container_of(qedf_dbg,
 126            struct qedf_ctx, dbg_ctx);
 127
 128        QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "entered\n");
 129
 130        cnt = sprintf(buffer, "\nFastpath I/O completions\n\n");
 131
 132        for (id = 0; id < qedf->num_queues; id++) {
 133                fp = &(qedf->fp_array[id]);
 134                if (fp->sb_id == QEDF_SB_ID_NULL)
 135                        continue;
 136                cnt += sprintf((buffer + cnt), "#%d: %lu\n", id,
 137                               fp->completions);
 138        }
 139
 140        cnt = min_t(int, count, cnt - *ppos);
 141        *ppos += cnt;
 142        return cnt;
 143}
 144
 145static ssize_t
 146qedf_dbg_fp_int_cmd_write(struct file *filp, const char __user *buffer,
 147                          size_t count, loff_t *ppos)
 148{
 149        if (!count || *ppos)
 150                return 0;
 151
 152        return count;
 153}
 154
 155static ssize_t
 156qedf_dbg_debug_cmd_read(struct file *filp, char __user *buffer, size_t count,
 157                        loff_t *ppos)
 158{
 159        int cnt;
 160        struct qedf_dbg_ctx *qedf =
 161                                (struct qedf_dbg_ctx *)filp->private_data;
 162
 163        QEDF_INFO(qedf, QEDF_LOG_DEBUGFS, "entered\n");
 164        cnt = sprintf(buffer, "debug mask = 0x%x\n", qedf_debug);
 165
 166        cnt = min_t(int, count, cnt - *ppos);
 167        *ppos += cnt;
 168        return cnt;
 169}
 170
 171static ssize_t
 172qedf_dbg_debug_cmd_write(struct file *filp, const char __user *buffer,
 173                         size_t count, loff_t *ppos)
 174{
 175        uint32_t val;
 176        void *kern_buf;
 177        int rval;
 178        struct qedf_dbg_ctx *qedf =
 179            (struct qedf_dbg_ctx *)filp->private_data;
 180
 181        if (!count || *ppos)
 182                return 0;
 183
 184        kern_buf = memdup_user(buffer, count);
 185        if (IS_ERR(kern_buf))
 186                return PTR_ERR(kern_buf);
 187
 188        rval = kstrtouint(kern_buf, 10, &val);
 189        kfree(kern_buf);
 190        if (rval)
 191                return rval;
 192
 193        if (val == 1)
 194                qedf_debug = QEDF_DEFAULT_LOG_MASK;
 195        else
 196                qedf_debug = val;
 197
 198        QEDF_INFO(qedf, QEDF_LOG_DEBUGFS, "Setting debug=0x%x.\n", val);
 199        return count;
 200}
 201
 202static ssize_t
 203qedf_dbg_stop_io_on_error_cmd_read(struct file *filp, char __user *buffer,
 204                                   size_t count, loff_t *ppos)
 205{
 206        int cnt;
 207        struct qedf_dbg_ctx *qedf_dbg =
 208                                (struct qedf_dbg_ctx *)filp->private_data;
 209        struct qedf_ctx *qedf = container_of(qedf_dbg,
 210            struct qedf_ctx, dbg_ctx);
 211
 212        QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "entered\n");
 213        cnt = sprintf(buffer, "%s\n",
 214            qedf->stop_io_on_error ? "true" : "false");
 215
 216        cnt = min_t(int, count, cnt - *ppos);
 217        *ppos += cnt;
 218        return cnt;
 219}
 220
 221static ssize_t
 222qedf_dbg_stop_io_on_error_cmd_write(struct file *filp,
 223                                    const char __user *buffer, size_t count,
 224                                    loff_t *ppos)
 225{
 226        void *kern_buf;
 227        struct qedf_dbg_ctx *qedf_dbg =
 228                                (struct qedf_dbg_ctx *)filp->private_data;
 229        struct qedf_ctx *qedf = container_of(qedf_dbg, struct qedf_ctx,
 230            dbg_ctx);
 231
 232        QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "entered\n");
 233
 234        if (!count || *ppos)
 235                return 0;
 236
 237        kern_buf = memdup_user(buffer, 6);
 238        if (IS_ERR(kern_buf))
 239                return PTR_ERR(kern_buf);
 240
 241        if (strncmp(kern_buf, "false", 5) == 0)
 242                qedf->stop_io_on_error = false;
 243        else if (strncmp(kern_buf, "true", 4) == 0)
 244                qedf->stop_io_on_error = true;
 245        else if (strncmp(kern_buf, "now", 3) == 0)
 246                /* Trigger from user to stop all I/O on this host */
 247                set_bit(QEDF_DBG_STOP_IO, &qedf->flags);
 248
 249        kfree(kern_buf);
 250        return count;
 251}
 252
 253static int
 254qedf_io_trace_show(struct seq_file *s, void *unused)
 255{
 256        int i, idx = 0;
 257        struct qedf_ctx *qedf = s->private;
 258        struct qedf_dbg_ctx *qedf_dbg = &qedf->dbg_ctx;
 259        struct qedf_io_log *io_log;
 260        unsigned long flags;
 261
 262        if (!qedf_io_tracing) {
 263                seq_puts(s, "I/O tracing not enabled.\n");
 264                goto out;
 265        }
 266
 267        QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "entered\n");
 268
 269        spin_lock_irqsave(&qedf->io_trace_lock, flags);
 270        idx = qedf->io_trace_idx;
 271        for (i = 0; i < QEDF_IO_TRACE_SIZE; i++) {
 272                io_log = &qedf->io_trace_buf[idx];
 273                seq_printf(s, "%d:", io_log->direction);
 274                seq_printf(s, "0x%x:", io_log->task_id);
 275                seq_printf(s, "0x%06x:", io_log->port_id);
 276                seq_printf(s, "%d:", io_log->lun);
 277                seq_printf(s, "0x%02x:", io_log->op);
 278                seq_printf(s, "0x%02x%02x%02x%02x:", io_log->lba[0],
 279                    io_log->lba[1], io_log->lba[2], io_log->lba[3]);
 280                seq_printf(s, "%d:", io_log->bufflen);
 281                seq_printf(s, "%d:", io_log->sg_count);
 282                seq_printf(s, "0x%08x:", io_log->result);
 283                seq_printf(s, "%lu:", io_log->jiffies);
 284                seq_printf(s, "%d:", io_log->refcount);
 285                seq_printf(s, "%d:", io_log->req_cpu);
 286                seq_printf(s, "%d:", io_log->int_cpu);
 287                seq_printf(s, "%d:", io_log->rsp_cpu);
 288                seq_printf(s, "%d\n", io_log->sge_type);
 289
 290                idx++;
 291                if (idx == QEDF_IO_TRACE_SIZE)
 292                        idx = 0;
 293        }
 294        spin_unlock_irqrestore(&qedf->io_trace_lock, flags);
 295
 296out:
 297        return 0;
 298}
 299
 300static int
 301qedf_dbg_io_trace_open(struct inode *inode, struct file *file)
 302{
 303        struct qedf_dbg_ctx *qedf_dbg = inode->i_private;
 304        struct qedf_ctx *qedf = container_of(qedf_dbg,
 305            struct qedf_ctx, dbg_ctx);
 306
 307        return single_open(file, qedf_io_trace_show, qedf);
 308}
 309
 310static int
 311qedf_driver_stats_show(struct seq_file *s, void *unused)
 312{
 313        struct qedf_ctx *qedf = s->private;
 314        struct qedf_rport *fcport;
 315        struct fc_rport_priv *rdata;
 316
 317        seq_printf(s, "cmg_mgr free io_reqs: %d\n",
 318            atomic_read(&qedf->cmd_mgr->free_list_cnt));
 319        seq_printf(s, "slow SGEs: %d\n", qedf->slow_sge_ios);
 320        seq_printf(s, "single SGEs: %d\n", qedf->single_sge_ios);
 321        seq_printf(s, "fast SGEs: %d\n\n", qedf->fast_sge_ios);
 322
 323        seq_puts(s, "Offloaded ports:\n\n");
 324
 325        rcu_read_lock();
 326        list_for_each_entry_rcu(fcport, &qedf->fcports, peers) {
 327                rdata = fcport->rdata;
 328                if (rdata == NULL)
 329                        continue;
 330                seq_printf(s, "%06x: free_sqes: %d, num_active_ios: %d\n",
 331                    rdata->ids.port_id, atomic_read(&fcport->free_sqes),
 332                    atomic_read(&fcport->num_active_ios));
 333        }
 334        rcu_read_unlock();
 335
 336        return 0;
 337}
 338
 339static int
 340qedf_dbg_driver_stats_open(struct inode *inode, struct file *file)
 341{
 342        struct qedf_dbg_ctx *qedf_dbg = inode->i_private;
 343        struct qedf_ctx *qedf = container_of(qedf_dbg,
 344            struct qedf_ctx, dbg_ctx);
 345
 346        return single_open(file, qedf_driver_stats_show, qedf);
 347}
 348
 349static ssize_t
 350qedf_dbg_clear_stats_cmd_read(struct file *filp, char __user *buffer,
 351                                   size_t count, loff_t *ppos)
 352{
 353        int cnt = 0;
 354
 355        /* Essentially a read stub */
 356        cnt = min_t(int, count, cnt - *ppos);
 357        *ppos += cnt;
 358        return cnt;
 359}
 360
 361static ssize_t
 362qedf_dbg_clear_stats_cmd_write(struct file *filp,
 363                                    const char __user *buffer, size_t count,
 364                                    loff_t *ppos)
 365{
 366        struct qedf_dbg_ctx *qedf_dbg =
 367                                (struct qedf_dbg_ctx *)filp->private_data;
 368        struct qedf_ctx *qedf = container_of(qedf_dbg, struct qedf_ctx,
 369            dbg_ctx);
 370
 371        QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "Clearing stat counters.\n");
 372
 373        if (!count || *ppos)
 374                return 0;
 375
 376        /* Clear stat counters exposed by 'stats' node */
 377        qedf->slow_sge_ios = 0;
 378        qedf->single_sge_ios = 0;
 379        qedf->fast_sge_ios = 0;
 380
 381        return count;
 382}
 383
 384static int
 385qedf_offload_stats_show(struct seq_file *s, void *unused)
 386{
 387        struct qedf_ctx *qedf = s->private;
 388        struct qed_fcoe_stats *fw_fcoe_stats;
 389
 390        fw_fcoe_stats = kmalloc(sizeof(struct qed_fcoe_stats), GFP_KERNEL);
 391        if (!fw_fcoe_stats) {
 392                QEDF_ERR(&(qedf->dbg_ctx), "Could not allocate memory for "
 393                    "fw_fcoe_stats.\n");
 394                goto out;
 395        }
 396
 397        /* Query firmware for offload stats */
 398        qed_ops->get_stats(qedf->cdev, fw_fcoe_stats);
 399
 400        seq_printf(s, "fcoe_rx_byte_cnt=%llu\n"
 401            "fcoe_rx_data_pkt_cnt=%llu\n"
 402            "fcoe_rx_xfer_pkt_cnt=%llu\n"
 403            "fcoe_rx_other_pkt_cnt=%llu\n"
 404            "fcoe_silent_drop_pkt_cmdq_full_cnt=%u\n"
 405            "fcoe_silent_drop_pkt_crc_error_cnt=%u\n"
 406            "fcoe_silent_drop_pkt_task_invalid_cnt=%u\n"
 407            "fcoe_silent_drop_total_pkt_cnt=%u\n"
 408            "fcoe_silent_drop_pkt_rq_full_cnt=%u\n"
 409            "fcoe_tx_byte_cnt=%llu\n"
 410            "fcoe_tx_data_pkt_cnt=%llu\n"
 411            "fcoe_tx_xfer_pkt_cnt=%llu\n"
 412            "fcoe_tx_other_pkt_cnt=%llu\n",
 413            fw_fcoe_stats->fcoe_rx_byte_cnt,
 414            fw_fcoe_stats->fcoe_rx_data_pkt_cnt,
 415            fw_fcoe_stats->fcoe_rx_xfer_pkt_cnt,
 416            fw_fcoe_stats->fcoe_rx_other_pkt_cnt,
 417            fw_fcoe_stats->fcoe_silent_drop_pkt_cmdq_full_cnt,
 418            fw_fcoe_stats->fcoe_silent_drop_pkt_crc_error_cnt,
 419            fw_fcoe_stats->fcoe_silent_drop_pkt_task_invalid_cnt,
 420            fw_fcoe_stats->fcoe_silent_drop_total_pkt_cnt,
 421            fw_fcoe_stats->fcoe_silent_drop_pkt_rq_full_cnt,
 422            fw_fcoe_stats->fcoe_tx_byte_cnt,
 423            fw_fcoe_stats->fcoe_tx_data_pkt_cnt,
 424            fw_fcoe_stats->fcoe_tx_xfer_pkt_cnt,
 425            fw_fcoe_stats->fcoe_tx_other_pkt_cnt);
 426
 427        kfree(fw_fcoe_stats);
 428out:
 429        return 0;
 430}
 431
 432static int
 433qedf_dbg_offload_stats_open(struct inode *inode, struct file *file)
 434{
 435        struct qedf_dbg_ctx *qedf_dbg = inode->i_private;
 436        struct qedf_ctx *qedf = container_of(qedf_dbg,
 437            struct qedf_ctx, dbg_ctx);
 438
 439        return single_open(file, qedf_offload_stats_show, qedf);
 440}
 441
 442const struct file_operations qedf_dbg_fops[] = {
 443        qedf_dbg_fileops(qedf, fp_int),
 444        qedf_dbg_fileops_seq(qedf, io_trace),
 445        qedf_dbg_fileops(qedf, debug),
 446        qedf_dbg_fileops(qedf, stop_io_on_error),
 447        qedf_dbg_fileops_seq(qedf, driver_stats),
 448        qedf_dbg_fileops(qedf, clear_stats),
 449        qedf_dbg_fileops_seq(qedf, offload_stats),
 450        /* This must be last */
 451        { },
 452};
 453
 454#else /* CONFIG_DEBUG_FS */
 455void qedf_dbg_host_init(struct qedf_dbg_ctx *);
 456void qedf_dbg_host_exit(struct qedf_dbg_ctx *);
 457void qedf_dbg_init(char *);
 458void qedf_dbg_exit(void);
 459#endif /* CONFIG_DEBUG_FS */
 460