linux/drivers/scsi/snic/snic_debugfs.c
<<
>>
Prefs
   1/*
   2 * Copyright 2014 Cisco Systems, Inc.  All rights reserved.
   3 *
   4 * This program is free software; you may redistribute it and/or modify
   5 * it under the terms of the GNU General Public License as published by
   6 * the Free Software Foundation; version 2 of the License.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   9 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  10 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  11 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  12 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  13 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  14 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  15 * SOFTWARE.
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/errno.h>
  20#include <linux/debugfs.h>
  21
  22#include "snic.h"
  23
  24/*
  25 * snic_debugfs_init - Initialize debugfs for snic debug logging
  26 *
  27 * Description:
  28 * When Debugfs is configured this routine sets up fnic debugfs
  29 * filesystem. If not already created. this routine will crate the
  30 * fnic directory and statistics directory for trace buffer and
  31 * stats logging
  32 */
  33void snic_debugfs_init(void)
  34{
  35        snic_glob->trc_root = debugfs_create_dir("snic", NULL);
  36
  37        snic_glob->stats_root = debugfs_create_dir("statistics",
  38                                                   snic_glob->trc_root);
  39}
  40
  41/*
  42 * snic_debugfs_term - Tear down debugfs intrastructure
  43 *
  44 * Description:
  45 * When Debufs is configured this routine removes debugfs file system
  46 * elements that are specific to snic
  47 */
  48void
  49snic_debugfs_term(void)
  50{
  51        debugfs_remove(snic_glob->stats_root);
  52        snic_glob->stats_root = NULL;
  53
  54        debugfs_remove(snic_glob->trc_root);
  55        snic_glob->trc_root = NULL;
  56}
  57
  58/*
  59 * snic_reset_stats_open - Open the reset_stats file
  60 */
  61static int
  62snic_reset_stats_open(struct inode *inode, struct file *filp)
  63{
  64        SNIC_BUG_ON(!inode->i_private);
  65        filp->private_data = inode->i_private;
  66
  67        return 0;
  68}
  69
  70/*
  71 * snic_reset_stats_read - Read a reset_stats debugfs file
  72 * @filp: The file pointer to read from.
  73 * @ubuf: The buffer tocopy the data to.
  74 * @cnt: The number of bytes to read.
  75 * @ppos: The position in the file to start reading frm.
  76 *
  77 * Description:
  78 * This routine reads value of variable reset_stats
  79 * and stores into local @buf. It will start reading file @ppos and
  80 * copy up to @cnt of data to @ubuf from @buf.
  81 *
  82 * Returns:
  83 * This function returns the amount of data that was read.
  84 */
  85static ssize_t
  86snic_reset_stats_read(struct file *filp,
  87                      char __user *ubuf,
  88                      size_t cnt,
  89                      loff_t *ppos)
  90{
  91        struct snic *snic = (struct snic *) filp->private_data;
  92        char buf[64];
  93        int len;
  94
  95        len = sprintf(buf, "%u\n", snic->reset_stats);
  96
  97        return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
  98}
  99
 100/*
 101 * snic_reset_stats_write - Write to reset_stats debugfs file
 102 * @filp: The file pointer to write from
 103 * @ubuf: The buffer to copy the data from.
 104 * @cnt: The number of bytes to write.
 105 * @ppos: The position in the file to start writing to.
 106 *
 107 * Description:
 108 * This routine writes data from user buffer @ubuf to buffer @buf and
 109 * resets cumulative stats of snic.
 110 *
 111 * Returns:
 112 * This function returns the amount of data that was written.
 113 */
 114static ssize_t
 115snic_reset_stats_write(struct file *filp,
 116                       const char __user *ubuf,
 117                       size_t cnt,
 118                       loff_t *ppos)
 119{
 120        struct snic *snic = (struct snic *) filp->private_data;
 121        struct snic_stats *stats = &snic->s_stats;
 122        u64 *io_stats_p = (u64 *) &stats->io;
 123        u64 *fw_stats_p = (u64 *) &stats->fw;
 124        char buf[64];
 125        unsigned long val;
 126        int ret;
 127
 128        if (cnt >= sizeof(buf))
 129                return -EINVAL;
 130
 131        if (copy_from_user(&buf, ubuf, cnt))
 132                return -EFAULT;
 133
 134        buf[cnt] = '\0';
 135
 136        ret = kstrtoul(buf, 10, &val);
 137        if (ret < 0)
 138                return ret;
 139
 140        snic->reset_stats = val;
 141
 142        if (snic->reset_stats) {
 143                /* Skip variable is used to avoid descrepancies to Num IOs
 144                 * and IO Completions stats. Skip incrementing No IO Compls
 145                 * for pending active IOs after reset_stats
 146                 */
 147                atomic64_set(&snic->io_cmpl_skip,
 148                             atomic64_read(&stats->io.active));
 149                memset(&stats->abts, 0, sizeof(struct snic_abort_stats));
 150                memset(&stats->reset, 0, sizeof(struct snic_reset_stats));
 151                memset(&stats->misc, 0, sizeof(struct snic_misc_stats));
 152                memset(io_stats_p+1,
 153                        0,
 154                        sizeof(struct snic_io_stats) - sizeof(u64));
 155                memset(fw_stats_p+1,
 156                        0,
 157                        sizeof(struct snic_fw_stats) - sizeof(u64));
 158        }
 159
 160        (*ppos)++;
 161
 162        SNIC_HOST_INFO(snic->shost, "Reset Op: Driver statistics.\n");
 163
 164        return cnt;
 165}
 166
 167static int
 168snic_reset_stats_release(struct inode *inode, struct file *filp)
 169{
 170        filp->private_data = NULL;
 171
 172        return 0;
 173}
 174
 175/*
 176 * snic_stats_show - Formats and prints per host specific driver stats.
 177 */
 178static int
 179snic_stats_show(struct seq_file *sfp, void *data)
 180{
 181        struct snic *snic = (struct snic *) sfp->private;
 182        struct snic_stats *stats = &snic->s_stats;
 183        struct timespec64 last_isr_tms, last_ack_tms;
 184        u64 maxio_tm;
 185        int i;
 186
 187        /* Dump IO Stats */
 188        seq_printf(sfp,
 189                   "------------------------------------------\n"
 190                   "\t\t IO Statistics\n"
 191                   "------------------------------------------\n");
 192
 193        maxio_tm = (u64) atomic64_read(&stats->io.max_time);
 194        seq_printf(sfp,
 195                   "Active IOs                  : %lld\n"
 196                   "Max Active IOs              : %lld\n"
 197                   "Total IOs                   : %lld\n"
 198                   "IOs Completed               : %lld\n"
 199                   "IOs Failed                  : %lld\n"
 200                   "IOs Not Found               : %lld\n"
 201                   "Memory Alloc Failures       : %lld\n"
 202                   "REQs Null                   : %lld\n"
 203                   "SCSI Cmd Pointers Null      : %lld\n"
 204                   "Max SGL for any IO          : %lld\n"
 205                   "Max IO Size                 : %lld Sectors\n"
 206                   "Max Queuing Time            : %lld\n"
 207                   "Max Completion Time         : %lld\n"
 208                   "Max IO Process Time(FW)     : %lld (%u msec)\n",
 209                   (u64) atomic64_read(&stats->io.active),
 210                   (u64) atomic64_read(&stats->io.max_active),
 211                   (u64) atomic64_read(&stats->io.num_ios),
 212                   (u64) atomic64_read(&stats->io.compl),
 213                   (u64) atomic64_read(&stats->io.fail),
 214                   (u64) atomic64_read(&stats->io.io_not_found),
 215                   (u64) atomic64_read(&stats->io.alloc_fail),
 216                   (u64) atomic64_read(&stats->io.req_null),
 217                   (u64) atomic64_read(&stats->io.sc_null),
 218                   (u64) atomic64_read(&stats->io.max_sgl),
 219                   (u64) atomic64_read(&stats->io.max_io_sz),
 220                   (u64) atomic64_read(&stats->io.max_qtime),
 221                   (u64) atomic64_read(&stats->io.max_cmpl_time),
 222                   maxio_tm,
 223                   jiffies_to_msecs(maxio_tm));
 224
 225        seq_puts(sfp, "\nSGL Counters\n");
 226
 227        for (i = 0; i < SNIC_MAX_SG_DESC_CNT; i++) {
 228                seq_printf(sfp,
 229                           "%10lld ",
 230                           (u64) atomic64_read(&stats->io.sgl_cnt[i]));
 231
 232                if ((i + 1) % 8 == 0)
 233                        seq_puts(sfp, "\n");
 234        }
 235
 236        /* Dump Abort Stats */
 237        seq_printf(sfp,
 238                   "\n-------------------------------------------\n"
 239                   "\t\t Abort Statistics\n"
 240                   "---------------------------------------------\n");
 241
 242        seq_printf(sfp,
 243                   "Aborts                      : %lld\n"
 244                   "Aborts Fail                 : %lld\n"
 245                   "Aborts Driver Timeout       : %lld\n"
 246                   "Abort FW Timeout            : %lld\n"
 247                   "Abort IO NOT Found          : %lld\n"
 248                   "Abort Queuing Failed        : %lld\n",
 249                   (u64) atomic64_read(&stats->abts.num),
 250                   (u64) atomic64_read(&stats->abts.fail),
 251                   (u64) atomic64_read(&stats->abts.drv_tmo),
 252                   (u64) atomic64_read(&stats->abts.fw_tmo),
 253                   (u64) atomic64_read(&stats->abts.io_not_found),
 254                   (u64) atomic64_read(&stats->abts.q_fail));
 255
 256        /* Dump Reset Stats */
 257        seq_printf(sfp,
 258                   "\n-------------------------------------------\n"
 259                   "\t\t Reset Statistics\n"
 260                   "---------------------------------------------\n");
 261
 262        seq_printf(sfp,
 263                   "HBA Resets                  : %lld\n"
 264                   "HBA Reset Cmpls             : %lld\n"
 265                   "HBA Reset Fail              : %lld\n",
 266                   (u64) atomic64_read(&stats->reset.hba_resets),
 267                   (u64) atomic64_read(&stats->reset.hba_reset_cmpl),
 268                   (u64) atomic64_read(&stats->reset.hba_reset_fail));
 269
 270        /* Dump Firmware Stats */
 271        seq_printf(sfp,
 272                   "\n-------------------------------------------\n"
 273                   "\t\t Firmware Statistics\n"
 274                   "---------------------------------------------\n");
 275
 276        seq_printf(sfp,
 277                "Active FW Requests             : %lld\n"
 278                "Max FW Requests                : %lld\n"
 279                "FW Out Of Resource Errs        : %lld\n"
 280                "FW IO Errors                   : %lld\n"
 281                "FW SCSI Errors                 : %lld\n",
 282                (u64) atomic64_read(&stats->fw.actv_reqs),
 283                (u64) atomic64_read(&stats->fw.max_actv_reqs),
 284                (u64) atomic64_read(&stats->fw.out_of_res),
 285                (u64) atomic64_read(&stats->fw.io_errs),
 286                (u64) atomic64_read(&stats->fw.scsi_errs));
 287
 288
 289        /* Dump Miscellenous Stats */
 290        seq_printf(sfp,
 291                   "\n---------------------------------------------\n"
 292                   "\t\t Other Statistics\n"
 293                   "\n---------------------------------------------\n");
 294
 295        jiffies_to_timespec64(stats->misc.last_isr_time, &last_isr_tms);
 296        jiffies_to_timespec64(stats->misc.last_ack_time, &last_ack_tms);
 297
 298        seq_printf(sfp,
 299                   "Last ISR Time               : %llu (%8llu.%09lu)\n"
 300                   "Last Ack Time               : %llu (%8llu.%09lu)\n"
 301                   "Ack ISRs                    : %llu\n"
 302                   "IO Cmpl ISRs                : %llu\n"
 303                   "Err Notify ISRs             : %llu\n"
 304                   "Max CQ Entries              : %lld\n"
 305                   "Data Count Mismatch         : %lld\n"
 306                   "IOs w/ Timeout Status       : %lld\n"
 307                   "IOs w/ Aborted Status       : %lld\n"
 308                   "IOs w/ SGL Invalid Stat     : %lld\n"
 309                   "WQ Desc Alloc Fail          : %lld\n"
 310                   "Queue Full                  : %lld\n"
 311                   "Queue Ramp Up               : %lld\n"
 312                   "Queue Ramp Down             : %lld\n"
 313                   "Queue Last Queue Depth      : %lld\n"
 314                   "Target Not Ready            : %lld\n",
 315                   (u64) stats->misc.last_isr_time,
 316                   last_isr_tms.tv_sec, last_isr_tms.tv_nsec,
 317                   (u64)stats->misc.last_ack_time,
 318                   last_ack_tms.tv_sec, last_ack_tms.tv_nsec,
 319                   (u64) atomic64_read(&stats->misc.ack_isr_cnt),
 320                   (u64) atomic64_read(&stats->misc.cmpl_isr_cnt),
 321                   (u64) atomic64_read(&stats->misc.errnotify_isr_cnt),
 322                   (u64) atomic64_read(&stats->misc.max_cq_ents),
 323                   (u64) atomic64_read(&stats->misc.data_cnt_mismat),
 324                   (u64) atomic64_read(&stats->misc.io_tmo),
 325                   (u64) atomic64_read(&stats->misc.io_aborted),
 326                   (u64) atomic64_read(&stats->misc.sgl_inval),
 327                   (u64) atomic64_read(&stats->misc.wq_alloc_fail),
 328                   (u64) atomic64_read(&stats->misc.qfull),
 329                   (u64) atomic64_read(&stats->misc.qsz_rampup),
 330                   (u64) atomic64_read(&stats->misc.qsz_rampdown),
 331                   (u64) atomic64_read(&stats->misc.last_qsz),
 332                   (u64) atomic64_read(&stats->misc.tgt_not_rdy));
 333
 334        return 0;
 335}
 336
 337/*
 338 * snic_stats_open - Open the stats file for specific host
 339 *
 340 * Description:
 341 * This routine opens a debugfs file stats of specific host
 342 */
 343static int
 344snic_stats_open(struct inode *inode, struct file *filp)
 345{
 346        return single_open(filp, snic_stats_show, inode->i_private);
 347}
 348
 349static const struct file_operations snic_stats_fops = {
 350        .owner  = THIS_MODULE,
 351        .open   = snic_stats_open,
 352        .read   = seq_read,
 353        .llseek = seq_lseek,
 354        .release = single_release,
 355};
 356
 357static const struct file_operations snic_reset_stats_fops = {
 358        .owner = THIS_MODULE,
 359        .open = snic_reset_stats_open,
 360        .read = snic_reset_stats_read,
 361        .write = snic_reset_stats_write,
 362        .release = snic_reset_stats_release,
 363};
 364
 365/*
 366 * snic_stats_init - Initialize stats struct and create stats file
 367 * per snic
 368 *
 369 * Description:
 370 * When debugfs is cofigured this routine sets up the stats file per snic
 371 * It will create file stats and reset_stats under statistics/host# directory
 372 * to log per snic stats
 373 */
 374void snic_stats_debugfs_init(struct snic *snic)
 375{
 376        char name[16];
 377
 378        snprintf(name, sizeof(name), "host%d", snic->shost->host_no);
 379
 380        snic->stats_host = debugfs_create_dir(name, snic_glob->stats_root);
 381
 382        snic->stats_file = debugfs_create_file("stats", S_IFREG|S_IRUGO,
 383                                               snic->stats_host, snic,
 384                                               &snic_stats_fops);
 385
 386        snic->reset_stats_file = debugfs_create_file("reset_stats",
 387                                                     S_IFREG|S_IRUGO|S_IWUSR,
 388                                                     snic->stats_host, snic,
 389                                                     &snic_reset_stats_fops);
 390}
 391
 392/*
 393 * snic_stats_debugfs_remove - Tear down debugfs infrastructure of stats
 394 *
 395 * Description:
 396 * When Debufs is configured this routine removes debugfs file system
 397 * elements that are specific to to snic stats
 398 */
 399void
 400snic_stats_debugfs_remove(struct snic *snic)
 401{
 402        debugfs_remove(snic->stats_file);
 403        snic->stats_file = NULL;
 404
 405        debugfs_remove(snic->reset_stats_file);
 406        snic->reset_stats_file = NULL;
 407
 408        debugfs_remove(snic->stats_host);
 409        snic->stats_host = NULL;
 410}
 411
 412/* Trace Facility related API */
 413static void *
 414snic_trc_seq_start(struct seq_file *sfp, loff_t *pos)
 415{
 416        return &snic_glob->trc;
 417}
 418
 419static void *
 420snic_trc_seq_next(struct seq_file *sfp, void *data, loff_t *pos)
 421{
 422        return NULL;
 423}
 424
 425static void
 426snic_trc_seq_stop(struct seq_file *sfp, void *data)
 427{
 428}
 429
 430#define SNIC_TRC_PBLEN  256
 431static int
 432snic_trc_seq_show(struct seq_file *sfp, void *data)
 433{
 434        char buf[SNIC_TRC_PBLEN];
 435
 436        if (snic_get_trc_data(buf, SNIC_TRC_PBLEN) > 0)
 437                seq_printf(sfp, "%s\n", buf);
 438
 439        return 0;
 440}
 441
 442static const struct seq_operations snic_trc_seq_ops = {
 443        .start  = snic_trc_seq_start,
 444        .next   = snic_trc_seq_next,
 445        .stop   = snic_trc_seq_stop,
 446        .show   = snic_trc_seq_show,
 447};
 448
 449static int
 450snic_trc_open(struct inode *inode, struct file *filp)
 451{
 452        return seq_open(filp, &snic_trc_seq_ops);
 453}
 454
 455static const struct file_operations snic_trc_fops = {
 456        .owner  = THIS_MODULE,
 457        .open   = snic_trc_open,
 458        .read   = seq_read,
 459        .llseek = seq_lseek,
 460        .release = seq_release,
 461};
 462
 463/*
 464 * snic_trc_debugfs_init : creates trace/tracing_enable files for trace
 465 * under debugfs
 466 */
 467void snic_trc_debugfs_init(void)
 468{
 469        snic_glob->trc.trc_enable = debugfs_create_bool("tracing_enable",
 470                                                        S_IFREG | S_IRUGO | S_IWUSR,
 471                                                        snic_glob->trc_root,
 472                                                        &snic_glob->trc.enable);
 473
 474        snic_glob->trc.trc_file = debugfs_create_file("trace",
 475                                                      S_IFREG | S_IRUGO | S_IWUSR,
 476                                                      snic_glob->trc_root, NULL,
 477                                                      &snic_trc_fops);
 478}
 479
 480/*
 481 * snic_trc_debugfs_term : cleans up the files created for trace under debugfs
 482 */
 483void
 484snic_trc_debugfs_term(void)
 485{
 486        debugfs_remove(snic_glob->trc.trc_file);
 487        snic_glob->trc.trc_file = NULL;
 488
 489        debugfs_remove(snic_glob->trc.trc_enable);
 490        snic_glob->trc.trc_enable = NULL;
 491}
 492