linux/drivers/scsi/lpfc/lpfc_debugfs.c
<<
>>
Prefs
   1/*******************************************************************
   2 * This file is part of the Emulex Linux Device Driver for         *
   3 * Fibre Channel Host Bus Adapters.                                *
   4 * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
   5 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.  *
   6 * Copyright (C) 2007-2015 Emulex.  All rights reserved.           *
   7 * EMULEX and SLI are trademarks of Emulex.                        *
   8 * www.broadcom.com                                                *
   9 *                                                                 *
  10 * This program is free software; you can redistribute it and/or   *
  11 * modify it under the terms of version 2 of the GNU General       *
  12 * Public License as published by the Free Software Foundation.    *
  13 * This program is distributed in the hope that it will be useful. *
  14 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
  15 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
  16 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
  17 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
  18 * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
  19 * more details, a copy of which can be found in the file COPYING  *
  20 * included with this package.                                     *
  21 *******************************************************************/
  22
  23#include <linux/blkdev.h>
  24#include <linux/delay.h>
  25#include <linux/module.h>
  26#include <linux/dma-mapping.h>
  27#include <linux/idr.h>
  28#include <linux/interrupt.h>
  29#include <linux/kthread.h>
  30#include <linux/slab.h>
  31#include <linux/pci.h>
  32#include <linux/spinlock.h>
  33#include <linux/ctype.h>
  34
  35#include <scsi/scsi.h>
  36#include <scsi/scsi_device.h>
  37#include <scsi/scsi_host.h>
  38#include <scsi/scsi_transport_fc.h>
  39#include <scsi/fc/fc_fs.h>
  40
  41#include <linux/nvme-fc-driver.h>
  42
  43#include "lpfc_hw4.h"
  44#include "lpfc_hw.h"
  45#include "lpfc_sli.h"
  46#include "lpfc_sli4.h"
  47#include "lpfc_nl.h"
  48#include "lpfc_disc.h"
  49#include "lpfc.h"
  50#include "lpfc_scsi.h"
  51#include "lpfc_nvme.h"
  52#include "lpfc_nvmet.h"
  53#include "lpfc_logmsg.h"
  54#include "lpfc_crtn.h"
  55#include "lpfc_vport.h"
  56#include "lpfc_version.h"
  57#include "lpfc_compat.h"
  58#include "lpfc_debugfs.h"
  59#include "lpfc_bsg.h"
  60
  61#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
  62/*
  63 * debugfs interface
  64 *
  65 * To access this interface the user should:
  66 * # mount -t debugfs none /sys/kernel/debug
  67 *
  68 * The lpfc debugfs directory hierarchy is:
  69 * /sys/kernel/debug/lpfc/fnX/vportY
  70 * where X is the lpfc hba function unique_id
  71 * where Y is the vport VPI on that hba
  72 *
  73 * Debugging services available per vport:
  74 * discovery_trace
  75 * This is an ACSII readable file that contains a trace of the last
  76 * lpfc_debugfs_max_disc_trc events that happened on a specific vport.
  77 * See lpfc_debugfs.h for different categories of  discovery events.
  78 * To enable the discovery trace, the following module parameters must be set:
  79 * lpfc_debugfs_enable=1         Turns on lpfc debugfs filesystem support
  80 * lpfc_debugfs_max_disc_trc=X   Where X is the event trace depth for
  81 *                               EACH vport. X MUST also be a power of 2.
  82 * lpfc_debugfs_mask_disc_trc=Y  Where Y is an event mask as defined in
  83 *                               lpfc_debugfs.h .
  84 *
  85 * slow_ring_trace
  86 * This is an ACSII readable file that contains a trace of the last
  87 * lpfc_debugfs_max_slow_ring_trc events that happened on a specific HBA.
  88 * To enable the slow ring trace, the following module parameters must be set:
  89 * lpfc_debugfs_enable=1         Turns on lpfc debugfs filesystem support
  90 * lpfc_debugfs_max_slow_ring_trc=X   Where X is the event trace depth for
  91 *                               the HBA. X MUST also be a power of 2.
  92 */
  93static int lpfc_debugfs_enable = 1;
  94module_param(lpfc_debugfs_enable, int, S_IRUGO);
  95MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services");
  96
  97/* This MUST be a power of 2 */
  98static int lpfc_debugfs_max_disc_trc;
  99module_param(lpfc_debugfs_max_disc_trc, int, S_IRUGO);
 100MODULE_PARM_DESC(lpfc_debugfs_max_disc_trc,
 101        "Set debugfs discovery trace depth");
 102
 103/* This MUST be a power of 2 */
 104static int lpfc_debugfs_max_slow_ring_trc;
 105module_param(lpfc_debugfs_max_slow_ring_trc, int, S_IRUGO);
 106MODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc,
 107        "Set debugfs slow ring trace depth");
 108
 109/* This MUST be a power of 2 */
 110static int lpfc_debugfs_max_nvmeio_trc;
 111module_param(lpfc_debugfs_max_nvmeio_trc, int, 0444);
 112MODULE_PARM_DESC(lpfc_debugfs_max_nvmeio_trc,
 113                 "Set debugfs NVME IO trace depth");
 114
 115static int lpfc_debugfs_mask_disc_trc;
 116module_param(lpfc_debugfs_mask_disc_trc, int, S_IRUGO);
 117MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc,
 118        "Set debugfs discovery trace mask");
 119
 120#include <linux/debugfs.h>
 121
 122static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0);
 123static unsigned long lpfc_debugfs_start_time = 0L;
 124
 125/* iDiag */
 126static struct lpfc_idiag idiag;
 127
 128/**
 129 * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer
 130 * @vport: The vport to gather the log info from.
 131 * @buf: The buffer to dump log into.
 132 * @size: The maximum amount of data to process.
 133 *
 134 * Description:
 135 * This routine gathers the lpfc discovery debugfs data from the @vport and
 136 * dumps it to @buf up to @size number of bytes. It will start at the next entry
 137 * in the log and process the log until the end of the buffer. Then it will
 138 * gather from the beginning of the log and process until the current entry.
 139 *
 140 * Notes:
 141 * Discovery logging will be disabled while while this routine dumps the log.
 142 *
 143 * Return Value:
 144 * This routine returns the amount of bytes that were dumped into @buf and will
 145 * not exceed @size.
 146 **/
 147static int
 148lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
 149{
 150        int i, index, len, enable;
 151        uint32_t ms;
 152        struct lpfc_debugfs_trc *dtp;
 153        char *buffer;
 154
 155        buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL);
 156        if (!buffer)
 157                return 0;
 158
 159        enable = lpfc_debugfs_enable;
 160        lpfc_debugfs_enable = 0;
 161
 162        len = 0;
 163        index = (atomic_read(&vport->disc_trc_cnt) + 1) &
 164                (lpfc_debugfs_max_disc_trc - 1);
 165        for (i = index; i < lpfc_debugfs_max_disc_trc; i++) {
 166                dtp = vport->disc_trc + i;
 167                if (!dtp->fmt)
 168                        continue;
 169                ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
 170                snprintf(buffer,
 171                        LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
 172                        dtp->seq_cnt, ms, dtp->fmt);
 173                len +=  scnprintf(buf+len, size-len, buffer,
 174                        dtp->data1, dtp->data2, dtp->data3);
 175        }
 176        for (i = 0; i < index; i++) {
 177                dtp = vport->disc_trc + i;
 178                if (!dtp->fmt)
 179                        continue;
 180                ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
 181                snprintf(buffer,
 182                        LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
 183                        dtp->seq_cnt, ms, dtp->fmt);
 184                len +=  scnprintf(buf+len, size-len, buffer,
 185                        dtp->data1, dtp->data2, dtp->data3);
 186        }
 187
 188        lpfc_debugfs_enable = enable;
 189        kfree(buffer);
 190
 191        return len;
 192}
 193
 194/**
 195 * lpfc_debugfs_slow_ring_trc_data - Dump slow ring logging to a buffer
 196 * @phba: The HBA to gather the log info from.
 197 * @buf: The buffer to dump log into.
 198 * @size: The maximum amount of data to process.
 199 *
 200 * Description:
 201 * This routine gathers the lpfc slow ring debugfs data from the @phba and
 202 * dumps it to @buf up to @size number of bytes. It will start at the next entry
 203 * in the log and process the log until the end of the buffer. Then it will
 204 * gather from the beginning of the log and process until the current entry.
 205 *
 206 * Notes:
 207 * Slow ring logging will be disabled while while this routine dumps the log.
 208 *
 209 * Return Value:
 210 * This routine returns the amount of bytes that were dumped into @buf and will
 211 * not exceed @size.
 212 **/
 213static int
 214lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
 215{
 216        int i, index, len, enable;
 217        uint32_t ms;
 218        struct lpfc_debugfs_trc *dtp;
 219        char *buffer;
 220
 221        buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL);
 222        if (!buffer)
 223                return 0;
 224
 225        enable = lpfc_debugfs_enable;
 226        lpfc_debugfs_enable = 0;
 227
 228        len = 0;
 229        index = (atomic_read(&phba->slow_ring_trc_cnt) + 1) &
 230                (lpfc_debugfs_max_slow_ring_trc - 1);
 231        for (i = index; i < lpfc_debugfs_max_slow_ring_trc; i++) {
 232                dtp = phba->slow_ring_trc + i;
 233                if (!dtp->fmt)
 234                        continue;
 235                ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
 236                snprintf(buffer,
 237                        LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
 238                        dtp->seq_cnt, ms, dtp->fmt);
 239                len +=  scnprintf(buf+len, size-len, buffer,
 240                        dtp->data1, dtp->data2, dtp->data3);
 241        }
 242        for (i = 0; i < index; i++) {
 243                dtp = phba->slow_ring_trc + i;
 244                if (!dtp->fmt)
 245                        continue;
 246                ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
 247                snprintf(buffer,
 248                        LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
 249                        dtp->seq_cnt, ms, dtp->fmt);
 250                len +=  scnprintf(buf+len, size-len, buffer,
 251                        dtp->data1, dtp->data2, dtp->data3);
 252        }
 253
 254        lpfc_debugfs_enable = enable;
 255        kfree(buffer);
 256
 257        return len;
 258}
 259
 260static int lpfc_debugfs_last_hbq = -1;
 261
 262/**
 263 * lpfc_debugfs_hbqinfo_data - Dump host buffer queue info to a buffer
 264 * @phba: The HBA to gather host buffer info from.
 265 * @buf: The buffer to dump log into.
 266 * @size: The maximum amount of data to process.
 267 *
 268 * Description:
 269 * This routine dumps the host buffer queue info from the @phba to @buf up to
 270 * @size number of bytes. A header that describes the current hbq state will be
 271 * dumped to @buf first and then info on each hbq entry will be dumped to @buf
 272 * until @size bytes have been dumped or all the hbq info has been dumped.
 273 *
 274 * Notes:
 275 * This routine will rotate through each configured HBQ each time called.
 276 *
 277 * Return Value:
 278 * This routine returns the amount of bytes that were dumped into @buf and will
 279 * not exceed @size.
 280 **/
 281static int
 282lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size)
 283{
 284        int len = 0;
 285        int i, j, found, posted, low;
 286        uint32_t phys, raw_index, getidx;
 287        struct lpfc_hbq_init *hip;
 288        struct hbq_s *hbqs;
 289        struct lpfc_hbq_entry *hbqe;
 290        struct lpfc_dmabuf *d_buf;
 291        struct hbq_dmabuf *hbq_buf;
 292
 293        if (phba->sli_rev != 3)
 294                return 0;
 295
 296        spin_lock_irq(&phba->hbalock);
 297
 298        /* toggle between multiple hbqs, if any */
 299        i = lpfc_sli_hbq_count();
 300        if (i > 1) {
 301                 lpfc_debugfs_last_hbq++;
 302                 if (lpfc_debugfs_last_hbq >= i)
 303                        lpfc_debugfs_last_hbq = 0;
 304        }
 305        else
 306                lpfc_debugfs_last_hbq = 0;
 307
 308        i = lpfc_debugfs_last_hbq;
 309
 310        len +=  scnprintf(buf+len, size-len, "HBQ %d Info\n", i);
 311
 312        hbqs =  &phba->hbqs[i];
 313        posted = 0;
 314        list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list)
 315                posted++;
 316
 317        hip =  lpfc_hbq_defs[i];
 318        len +=  scnprintf(buf+len, size-len,
 319                "idx:%d prof:%d rn:%d bufcnt:%d icnt:%d acnt:%d posted %d\n",
 320                hip->hbq_index, hip->profile, hip->rn,
 321                hip->buffer_count, hip->init_count, hip->add_count, posted);
 322
 323        raw_index = phba->hbq_get[i];
 324        getidx = le32_to_cpu(raw_index);
 325        len +=  scnprintf(buf+len, size-len,
 326                "entries:%d bufcnt:%d Put:%d nPut:%d localGet:%d hbaGet:%d\n",
 327                hbqs->entry_count, hbqs->buffer_count, hbqs->hbqPutIdx,
 328                hbqs->next_hbqPutIdx, hbqs->local_hbqGetIdx, getidx);
 329
 330        hbqe = (struct lpfc_hbq_entry *) phba->hbqs[i].hbq_virt;
 331        for (j=0; j<hbqs->entry_count; j++) {
 332                len +=  scnprintf(buf+len, size-len,
 333                        "%03d: %08x %04x %05x ", j,
 334                        le32_to_cpu(hbqe->bde.addrLow),
 335                        le32_to_cpu(hbqe->bde.tus.w),
 336                        le32_to_cpu(hbqe->buffer_tag));
 337                i = 0;
 338                found = 0;
 339
 340                /* First calculate if slot has an associated posted buffer */
 341                low = hbqs->hbqPutIdx - posted;
 342                if (low >= 0) {
 343                        if ((j >= hbqs->hbqPutIdx) || (j < low)) {
 344                                len +=  scnprintf(buf + len, size - len,
 345                                                "Unused\n");
 346                                goto skipit;
 347                        }
 348                }
 349                else {
 350                        if ((j >= hbqs->hbqPutIdx) &&
 351                                (j < (hbqs->entry_count+low))) {
 352                                len +=  scnprintf(buf + len, size - len,
 353                                                "Unused\n");
 354                                goto skipit;
 355                        }
 356                }
 357
 358                /* Get the Buffer info for the posted buffer */
 359                list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list) {
 360                        hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf);
 361                        phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff);
 362                        if (phys == le32_to_cpu(hbqe->bde.addrLow)) {
 363                                len +=  scnprintf(buf+len, size-len,
 364                                        "Buf%d: %p %06x\n", i,
 365                                        hbq_buf->dbuf.virt, hbq_buf->tag);
 366                                found = 1;
 367                                break;
 368                        }
 369                        i++;
 370                }
 371                if (!found) {
 372                        len +=  scnprintf(buf+len, size-len, "No DMAinfo?\n");
 373                }
 374skipit:
 375                hbqe++;
 376                if (len > LPFC_HBQINFO_SIZE - 54)
 377                        break;
 378        }
 379        spin_unlock_irq(&phba->hbalock);
 380        return len;
 381}
 382
 383static int lpfc_debugfs_last_xripool;
 384
 385/**
 386 * lpfc_debugfs_common_xri_data - Dump Hardware Queue info to a buffer
 387 * @phba: The HBA to gather host buffer info from.
 388 * @buf: The buffer to dump log into.
 389 * @size: The maximum amount of data to process.
 390 *
 391 * Description:
 392 * This routine dumps the Hardware Queue info from the @phba to @buf up to
 393 * @size number of bytes. A header that describes the current hdwq state will be
 394 * dumped to @buf first and then info on each hdwq entry will be dumped to @buf
 395 * until @size bytes have been dumped or all the hdwq info has been dumped.
 396 *
 397 * Notes:
 398 * This routine will rotate through each configured Hardware Queue each
 399 * time called.
 400 *
 401 * Return Value:
 402 * This routine returns the amount of bytes that were dumped into @buf and will
 403 * not exceed @size.
 404 **/
 405static int
 406lpfc_debugfs_commonxripools_data(struct lpfc_hba *phba, char *buf, int size)
 407{
 408        struct lpfc_sli4_hdw_queue *qp;
 409        int len = 0;
 410        int i, out;
 411        unsigned long iflag;
 412
 413        for (i = 0; i < phba->cfg_hdw_queue; i++) {
 414                if (len > (LPFC_DUMP_MULTIXRIPOOL_SIZE - 80))
 415                        break;
 416                qp = &phba->sli4_hba.hdwq[lpfc_debugfs_last_xripool];
 417
 418                len += scnprintf(buf + len, size - len, "HdwQ %d Info ", i);
 419                spin_lock_irqsave(&qp->abts_scsi_buf_list_lock, iflag);
 420                spin_lock(&qp->abts_nvme_buf_list_lock);
 421                spin_lock(&qp->io_buf_list_get_lock);
 422                spin_lock(&qp->io_buf_list_put_lock);
 423                out = qp->total_io_bufs - (qp->get_io_bufs + qp->put_io_bufs +
 424                        qp->abts_scsi_io_bufs + qp->abts_nvme_io_bufs);
 425                len += scnprintf(buf + len, size - len,
 426                                 "tot:%d get:%d put:%d mt:%d "
 427                                 "ABTS scsi:%d nvme:%d Out:%d\n",
 428                        qp->total_io_bufs, qp->get_io_bufs, qp->put_io_bufs,
 429                        qp->empty_io_bufs, qp->abts_scsi_io_bufs,
 430                        qp->abts_nvme_io_bufs, out);
 431                spin_unlock(&qp->io_buf_list_put_lock);
 432                spin_unlock(&qp->io_buf_list_get_lock);
 433                spin_unlock(&qp->abts_nvme_buf_list_lock);
 434                spin_unlock_irqrestore(&qp->abts_scsi_buf_list_lock, iflag);
 435
 436                lpfc_debugfs_last_xripool++;
 437                if (lpfc_debugfs_last_xripool >= phba->cfg_hdw_queue)
 438                        lpfc_debugfs_last_xripool = 0;
 439        }
 440
 441        return len;
 442}
 443
 444/**
 445 * lpfc_debugfs_multixripools_data - Display multi-XRI pools information
 446 * @phba: The HBA to gather host buffer info from.
 447 * @buf: The buffer to dump log into.
 448 * @size: The maximum amount of data to process.
 449 *
 450 * Description:
 451 * This routine displays current multi-XRI pools information including XRI
 452 * count in public, private and txcmplq. It also displays current high and
 453 * low watermark.
 454 *
 455 * Return Value:
 456 * This routine returns the amount of bytes that were dumped into @buf and will
 457 * not exceed @size.
 458 **/
 459static int
 460lpfc_debugfs_multixripools_data(struct lpfc_hba *phba, char *buf, int size)
 461{
 462        u32 i;
 463        u32 hwq_count;
 464        struct lpfc_sli4_hdw_queue *qp;
 465        struct lpfc_multixri_pool *multixri_pool;
 466        struct lpfc_pvt_pool *pvt_pool;
 467        struct lpfc_pbl_pool *pbl_pool;
 468        u32 txcmplq_cnt;
 469        char tmp[LPFC_DEBUG_OUT_LINE_SZ] = {0};
 470
 471        if (phba->sli_rev != LPFC_SLI_REV4)
 472                return 0;
 473
 474        if (!phba->sli4_hba.hdwq)
 475                return 0;
 476
 477        if (!phba->cfg_xri_rebalancing) {
 478                i = lpfc_debugfs_commonxripools_data(phba, buf, size);
 479                return i;
 480        }
 481
 482        /*
 483         * Pbl: Current number of free XRIs in public pool
 484         * Pvt: Current number of free XRIs in private pool
 485         * Busy: Current number of outstanding XRIs
 486         * HWM: Current high watermark
 487         * pvt_empty: Incremented by 1 when IO submission fails (no xri)
 488         * pbl_empty: Incremented by 1 when all pbl_pool are empty during
 489         *            IO submission
 490         */
 491        scnprintf(tmp, sizeof(tmp),
 492                  "HWQ:  Pbl  Pvt Busy  HWM |  pvt_empty  pbl_empty ");
 493        if (strlcat(buf, tmp, size) >= size)
 494                return strnlen(buf, size);
 495
 496#ifdef LPFC_MXP_STAT
 497        /*
 498         * MAXH: Max high watermark seen so far
 499         * above_lmt: Incremented by 1 if xri_owned > xri_limit during
 500         *            IO submission
 501         * below_lmt: Incremented by 1 if xri_owned <= xri_limit  during
 502         *            IO submission
 503         * locPbl_hit: Incremented by 1 if successfully get a batch of XRI from
 504         *             local pbl_pool
 505         * othPbl_hit: Incremented by 1 if successfully get a batch of XRI from
 506         *             other pbl_pool
 507         */
 508        scnprintf(tmp, sizeof(tmp),
 509                  "MAXH  above_lmt  below_lmt locPbl_hit othPbl_hit");
 510        if (strlcat(buf, tmp, size) >= size)
 511                return strnlen(buf, size);
 512
 513        /*
 514         * sPbl: snapshot of Pbl 15 sec after stat gets cleared
 515         * sPvt: snapshot of Pvt 15 sec after stat gets cleared
 516         * sBusy: snapshot of Busy 15 sec after stat gets cleared
 517         */
 518        scnprintf(tmp, sizeof(tmp),
 519                  " | sPbl sPvt sBusy");
 520        if (strlcat(buf, tmp, size) >= size)
 521                return strnlen(buf, size);
 522#endif
 523
 524        scnprintf(tmp, sizeof(tmp), "\n");
 525        if (strlcat(buf, tmp, size) >= size)
 526                return strnlen(buf, size);
 527
 528        hwq_count = phba->cfg_hdw_queue;
 529        for (i = 0; i < hwq_count; i++) {
 530                qp = &phba->sli4_hba.hdwq[i];
 531                multixri_pool = qp->p_multixri_pool;
 532                if (!multixri_pool)
 533                        continue;
 534                pbl_pool = &multixri_pool->pbl_pool;
 535                pvt_pool = &multixri_pool->pvt_pool;
 536                txcmplq_cnt = qp->fcp_wq->pring->txcmplq_cnt;
 537                if (qp->nvme_wq)
 538                        txcmplq_cnt += qp->nvme_wq->pring->txcmplq_cnt;
 539
 540                scnprintf(tmp, sizeof(tmp),
 541                          "%03d: %4d %4d %4d %4d | %10d %10d ",
 542                          i, pbl_pool->count, pvt_pool->count,
 543                          txcmplq_cnt, pvt_pool->high_watermark,
 544                          qp->empty_io_bufs, multixri_pool->pbl_empty_count);
 545                if (strlcat(buf, tmp, size) >= size)
 546                        break;
 547
 548#ifdef LPFC_MXP_STAT
 549                scnprintf(tmp, sizeof(tmp),
 550                          "%4d %10d %10d %10d %10d",
 551                          multixri_pool->stat_max_hwm,
 552                          multixri_pool->above_limit_count,
 553                          multixri_pool->below_limit_count,
 554                          multixri_pool->local_pbl_hit_count,
 555                          multixri_pool->other_pbl_hit_count);
 556                if (strlcat(buf, tmp, size) >= size)
 557                        break;
 558
 559                scnprintf(tmp, sizeof(tmp),
 560                          " | %4d %4d %5d",
 561                          multixri_pool->stat_pbl_count,
 562                          multixri_pool->stat_pvt_count,
 563                          multixri_pool->stat_busy_count);
 564                if (strlcat(buf, tmp, size) >= size)
 565                        break;
 566#endif
 567
 568                scnprintf(tmp, sizeof(tmp), "\n");
 569                if (strlcat(buf, tmp, size) >= size)
 570                        break;
 571        }
 572        return strnlen(buf, size);
 573}
 574
 575
 576#ifdef LPFC_HDWQ_LOCK_STAT
 577static int lpfc_debugfs_last_lock;
 578
 579/**
 580 * lpfc_debugfs_lockstat_data - Dump Hardware Queue info to a buffer
 581 * @phba: The HBA to gather host buffer info from.
 582 * @buf: The buffer to dump log into.
 583 * @size: The maximum amount of data to process.
 584 *
 585 * Description:
 586 * This routine dumps the Hardware Queue info from the @phba to @buf up to
 587 * @size number of bytes. A header that describes the current hdwq state will be
 588 * dumped to @buf first and then info on each hdwq entry will be dumped to @buf
 589 * until @size bytes have been dumped or all the hdwq info has been dumped.
 590 *
 591 * Notes:
 592 * This routine will rotate through each configured Hardware Queue each
 593 * time called.
 594 *
 595 * Return Value:
 596 * This routine returns the amount of bytes that were dumped into @buf and will
 597 * not exceed @size.
 598 **/
 599static int
 600lpfc_debugfs_lockstat_data(struct lpfc_hba *phba, char *buf, int size)
 601{
 602        struct lpfc_sli4_hdw_queue *qp;
 603        int len = 0;
 604        int i;
 605
 606        if (phba->sli_rev != LPFC_SLI_REV4)
 607                return 0;
 608
 609        if (!phba->sli4_hba.hdwq)
 610                return 0;
 611
 612        for (i = 0; i < phba->cfg_hdw_queue; i++) {
 613                if (len > (LPFC_HDWQINFO_SIZE - 100))
 614                        break;
 615                qp = &phba->sli4_hba.hdwq[lpfc_debugfs_last_lock];
 616
 617                len += scnprintf(buf + len, size - len, "HdwQ %03d Lock ", i);
 618                if (phba->cfg_xri_rebalancing) {
 619                        len += scnprintf(buf + len, size - len,
 620                                         "get_pvt:%d mv_pvt:%d "
 621                                         "mv2pub:%d mv2pvt:%d "
 622                                         "put_pvt:%d put_pub:%d wq:%d\n",
 623                                         qp->lock_conflict.alloc_pvt_pool,
 624                                         qp->lock_conflict.mv_from_pvt_pool,
 625                                         qp->lock_conflict.mv_to_pub_pool,
 626                                         qp->lock_conflict.mv_to_pvt_pool,
 627                                         qp->lock_conflict.free_pvt_pool,
 628                                         qp->lock_conflict.free_pub_pool,
 629                                         qp->lock_conflict.wq_access);
 630                } else {
 631                        len += scnprintf(buf + len, size - len,
 632                                         "get:%d put:%d free:%d wq:%d\n",
 633                                         qp->lock_conflict.alloc_xri_get,
 634                                         qp->lock_conflict.alloc_xri_put,
 635                                         qp->lock_conflict.free_xri,
 636                                         qp->lock_conflict.wq_access);
 637                }
 638
 639                lpfc_debugfs_last_lock++;
 640                if (lpfc_debugfs_last_lock >= phba->cfg_hdw_queue)
 641                        lpfc_debugfs_last_lock = 0;
 642        }
 643
 644        return len;
 645}
 646#endif
 647
 648static int lpfc_debugfs_last_hba_slim_off;
 649
 650/**
 651 * lpfc_debugfs_dumpHBASlim_data - Dump HBA SLIM info to a buffer
 652 * @phba: The HBA to gather SLIM info from.
 653 * @buf: The buffer to dump log into.
 654 * @size: The maximum amount of data to process.
 655 *
 656 * Description:
 657 * This routine dumps the current contents of HBA SLIM for the HBA associated
 658 * with @phba to @buf up to @size bytes of data. This is the raw HBA SLIM data.
 659 *
 660 * Notes:
 661 * This routine will only dump up to 1024 bytes of data each time called and
 662 * should be called multiple times to dump the entire HBA SLIM.
 663 *
 664 * Return Value:
 665 * This routine returns the amount of bytes that were dumped into @buf and will
 666 * not exceed @size.
 667 **/
 668static int
 669lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
 670{
 671        int len = 0;
 672        int i, off;
 673        uint32_t *ptr;
 674        char *buffer;
 675
 676        buffer = kmalloc(1024, GFP_KERNEL);
 677        if (!buffer)
 678                return 0;
 679
 680        off = 0;
 681        spin_lock_irq(&phba->hbalock);
 682
 683        len +=  scnprintf(buf+len, size-len, "HBA SLIM\n");
 684        lpfc_memcpy_from_slim(buffer,
 685                phba->MBslimaddr + lpfc_debugfs_last_hba_slim_off, 1024);
 686
 687        ptr = (uint32_t *)&buffer[0];
 688        off = lpfc_debugfs_last_hba_slim_off;
 689
 690        /* Set it up for the next time */
 691        lpfc_debugfs_last_hba_slim_off += 1024;
 692        if (lpfc_debugfs_last_hba_slim_off >= 4096)
 693                lpfc_debugfs_last_hba_slim_off = 0;
 694
 695        i = 1024;
 696        while (i > 0) {
 697                len +=  scnprintf(buf+len, size-len,
 698                "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
 699                off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4),
 700                *(ptr+5), *(ptr+6), *(ptr+7));
 701                ptr += 8;
 702                i -= (8 * sizeof(uint32_t));
 703                off += (8 * sizeof(uint32_t));
 704        }
 705
 706        spin_unlock_irq(&phba->hbalock);
 707        kfree(buffer);
 708
 709        return len;
 710}
 711
 712/**
 713 * lpfc_debugfs_dumpHostSlim_data - Dump host SLIM info to a buffer
 714 * @phba: The HBA to gather Host SLIM info from.
 715 * @buf: The buffer to dump log into.
 716 * @size: The maximum amount of data to process.
 717 *
 718 * Description:
 719 * This routine dumps the current contents of host SLIM for the host associated
 720 * with @phba to @buf up to @size bytes of data. The dump will contain the
 721 * Mailbox, PCB, Rings, and Registers that are located in host memory.
 722 *
 723 * Return Value:
 724 * This routine returns the amount of bytes that were dumped into @buf and will
 725 * not exceed @size.
 726 **/
 727static int
 728lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size)
 729{
 730        int len = 0;
 731        int i, off;
 732        uint32_t word0, word1, word2, word3;
 733        uint32_t *ptr;
 734        struct lpfc_pgp *pgpp;
 735        struct lpfc_sli *psli = &phba->sli;
 736        struct lpfc_sli_ring *pring;
 737
 738        off = 0;
 739        spin_lock_irq(&phba->hbalock);
 740
 741        len +=  scnprintf(buf+len, size-len, "SLIM Mailbox\n");
 742        ptr = (uint32_t *)phba->slim2p.virt;
 743        i = sizeof(MAILBOX_t);
 744        while (i > 0) {
 745                len +=  scnprintf(buf+len, size-len,
 746                "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
 747                off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4),
 748                *(ptr+5), *(ptr+6), *(ptr+7));
 749                ptr += 8;
 750                i -= (8 * sizeof(uint32_t));
 751                off += (8 * sizeof(uint32_t));
 752        }
 753
 754        len +=  scnprintf(buf+len, size-len, "SLIM PCB\n");
 755        ptr = (uint32_t *)phba->pcb;
 756        i = sizeof(PCB_t);
 757        while (i > 0) {
 758                len +=  scnprintf(buf+len, size-len,
 759                "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
 760                off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4),
 761                *(ptr+5), *(ptr+6), *(ptr+7));
 762                ptr += 8;
 763                i -= (8 * sizeof(uint32_t));
 764                off += (8 * sizeof(uint32_t));
 765        }
 766
 767        if (phba->sli_rev <= LPFC_SLI_REV3) {
 768                for (i = 0; i < 4; i++) {
 769                        pgpp = &phba->port_gp[i];
 770                        pring = &psli->sli3_ring[i];
 771                        len +=  scnprintf(buf+len, size-len,
 772                                         "Ring %d: CMD GetInx:%d "
 773                                         "(Max:%d Next:%d "
 774                                         "Local:%d flg:x%x)  "
 775                                         "RSP PutInx:%d Max:%d\n",
 776                                         i, pgpp->cmdGetInx,
 777                                         pring->sli.sli3.numCiocb,
 778                                         pring->sli.sli3.next_cmdidx,
 779                                         pring->sli.sli3.local_getidx,
 780                                         pring->flag, pgpp->rspPutInx,
 781                                         pring->sli.sli3.numRiocb);
 782                }
 783
 784                word0 = readl(phba->HAregaddr);
 785                word1 = readl(phba->CAregaddr);
 786                word2 = readl(phba->HSregaddr);
 787                word3 = readl(phba->HCregaddr);
 788                len +=  scnprintf(buf+len, size-len, "HA:%08x CA:%08x HS:%08x "
 789                                 "HC:%08x\n", word0, word1, word2, word3);
 790        }
 791        spin_unlock_irq(&phba->hbalock);
 792        return len;
 793}
 794
 795/**
 796 * lpfc_debugfs_nodelist_data - Dump target node list to a buffer
 797 * @vport: The vport to gather target node info from.
 798 * @buf: The buffer to dump log into.
 799 * @size: The maximum amount of data to process.
 800 *
 801 * Description:
 802 * This routine dumps the current target node list associated with @vport to
 803 * @buf up to @size bytes of data. Each node entry in the dump will contain a
 804 * node state, DID, WWPN, WWNN, RPI, flags, type, and other useful fields.
 805 *
 806 * Return Value:
 807 * This routine returns the amount of bytes that were dumped into @buf and will
 808 * not exceed @size.
 809 **/
 810static int
 811lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
 812{
 813        int len = 0;
 814        int i, iocnt, outio, cnt;
 815        struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 816        struct lpfc_hba  *phba = vport->phba;
 817        struct lpfc_nodelist *ndlp;
 818        unsigned char *statep;
 819        struct nvme_fc_local_port *localport;
 820        struct nvme_fc_remote_port *nrport = NULL;
 821        struct lpfc_nvme_rport *rport;
 822
 823        cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
 824        outio = 0;
 825
 826        len += scnprintf(buf+len, size-len, "\nFCP Nodelist Entries ...\n");
 827        spin_lock_irq(shost->host_lock);
 828        list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
 829                iocnt = 0;
 830                if (!cnt) {
 831                        len +=  scnprintf(buf+len, size-len,
 832                                "Missing Nodelist Entries\n");
 833                        break;
 834                }
 835                cnt--;
 836                switch (ndlp->nlp_state) {
 837                case NLP_STE_UNUSED_NODE:
 838                        statep = "UNUSED";
 839                        break;
 840                case NLP_STE_PLOGI_ISSUE:
 841                        statep = "PLOGI ";
 842                        break;
 843                case NLP_STE_ADISC_ISSUE:
 844                        statep = "ADISC ";
 845                        break;
 846                case NLP_STE_REG_LOGIN_ISSUE:
 847                        statep = "REGLOG";
 848                        break;
 849                case NLP_STE_PRLI_ISSUE:
 850                        statep = "PRLI  ";
 851                        break;
 852                case NLP_STE_LOGO_ISSUE:
 853                        statep = "LOGO  ";
 854                        break;
 855                case NLP_STE_UNMAPPED_NODE:
 856                        statep = "UNMAP ";
 857                        iocnt = 1;
 858                        break;
 859                case NLP_STE_MAPPED_NODE:
 860                        statep = "MAPPED";
 861                        iocnt = 1;
 862                        break;
 863                case NLP_STE_NPR_NODE:
 864                        statep = "NPR   ";
 865                        break;
 866                default:
 867                        statep = "UNKNOWN";
 868                }
 869                len += scnprintf(buf+len, size-len, "%s DID:x%06x ",
 870                                statep, ndlp->nlp_DID);
 871                len += scnprintf(buf+len, size-len,
 872                                "WWPN x%llx ",
 873                                wwn_to_u64(ndlp->nlp_portname.u.wwn));
 874                len += scnprintf(buf+len, size-len,
 875                                "WWNN x%llx ",
 876                                wwn_to_u64(ndlp->nlp_nodename.u.wwn));
 877                if (ndlp->nlp_flag & NLP_RPI_REGISTERED)
 878                        len += scnprintf(buf+len, size-len, "RPI:%03d ",
 879                                        ndlp->nlp_rpi);
 880                else
 881                        len += scnprintf(buf+len, size-len, "RPI:none ");
 882                len +=  scnprintf(buf+len, size-len, "flag:x%08x ",
 883                        ndlp->nlp_flag);
 884                if (!ndlp->nlp_type)
 885                        len += scnprintf(buf+len, size-len, "UNKNOWN_TYPE ");
 886                if (ndlp->nlp_type & NLP_FC_NODE)
 887                        len += scnprintf(buf+len, size-len, "FC_NODE ");
 888                if (ndlp->nlp_type & NLP_FABRIC) {
 889                        len += scnprintf(buf+len, size-len, "FABRIC ");
 890                        iocnt = 0;
 891                }
 892                if (ndlp->nlp_type & NLP_FCP_TARGET)
 893                        len += scnprintf(buf+len, size-len, "FCP_TGT sid:%d ",
 894                                ndlp->nlp_sid);
 895                if (ndlp->nlp_type & NLP_FCP_INITIATOR)
 896                        len += scnprintf(buf+len, size-len, "FCP_INITIATOR ");
 897                if (ndlp->nlp_type & NLP_NVME_TARGET)
 898                        len += scnprintf(buf + len,
 899                                        size - len, "NVME_TGT sid:%d ",
 900                                        NLP_NO_SID);
 901                if (ndlp->nlp_type & NLP_NVME_INITIATOR)
 902                        len += scnprintf(buf + len,
 903                                        size - len, "NVME_INITIATOR ");
 904                len += scnprintf(buf+len, size-len, "usgmap:%x ",
 905                        ndlp->nlp_usg_map);
 906                len += scnprintf(buf+len, size-len, "refcnt:%x",
 907                        kref_read(&ndlp->kref));
 908                if (iocnt) {
 909                        i = atomic_read(&ndlp->cmd_pending);
 910                        len += scnprintf(buf + len, size - len,
 911                                        " OutIO:x%x Qdepth x%x",
 912                                        i, ndlp->cmd_qdepth);
 913                        outio += i;
 914                }
 915                len += scnprintf(buf + len, size - len, "defer:%x ",
 916                        ndlp->nlp_defer_did);
 917                len +=  scnprintf(buf+len, size-len, "\n");
 918        }
 919        spin_unlock_irq(shost->host_lock);
 920
 921        len += scnprintf(buf + len, size - len,
 922                        "\nOutstanding IO x%x\n",  outio);
 923
 924        if (phba->nvmet_support && phba->targetport && (vport == phba->pport)) {
 925                len += scnprintf(buf + len, size - len,
 926                                "\nNVME Targetport Entry ...\n");
 927
 928                /* Port state is only one of two values for now. */
 929                if (phba->targetport->port_id)
 930                        statep = "REGISTERED";
 931                else
 932                        statep = "INIT";
 933                len += scnprintf(buf + len, size - len,
 934                                "TGT WWNN x%llx WWPN x%llx State %s\n",
 935                                wwn_to_u64(vport->fc_nodename.u.wwn),
 936                                wwn_to_u64(vport->fc_portname.u.wwn),
 937                                statep);
 938                len += scnprintf(buf + len, size - len,
 939                                "    Targetport DID x%06x\n",
 940                                phba->targetport->port_id);
 941                goto out_exit;
 942        }
 943
 944        len += scnprintf(buf + len, size - len,
 945                                "\nNVME Lport/Rport Entries ...\n");
 946
 947        localport = vport->localport;
 948        if (!localport)
 949                goto out_exit;
 950
 951        spin_lock_irq(shost->host_lock);
 952
 953        /* Port state is only one of two values for now. */
 954        if (localport->port_id)
 955                statep = "ONLINE";
 956        else
 957                statep = "UNKNOWN ";
 958
 959        len += scnprintf(buf + len, size - len,
 960                        "Lport DID x%06x PortState %s\n",
 961                        localport->port_id, statep);
 962
 963        len += scnprintf(buf + len, size - len, "\tRport List:\n");
 964        list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
 965                /* local short-hand pointer. */
 966                spin_lock(&phba->hbalock);
 967                rport = lpfc_ndlp_get_nrport(ndlp);
 968                if (rport)
 969                        nrport = rport->remoteport;
 970                else
 971                        nrport = NULL;
 972                spin_unlock(&phba->hbalock);
 973                if (!nrport)
 974                        continue;
 975
 976                /* Port state is only one of two values for now. */
 977                switch (nrport->port_state) {
 978                case FC_OBJSTATE_ONLINE:
 979                        statep = "ONLINE";
 980                        break;
 981                case FC_OBJSTATE_UNKNOWN:
 982                        statep = "UNKNOWN ";
 983                        break;
 984                default:
 985                        statep = "UNSUPPORTED";
 986                        break;
 987                }
 988
 989                /* Tab in to show lport ownership. */
 990                len += scnprintf(buf + len, size - len,
 991                                "\t%s Port ID:x%06x ",
 992                                statep, nrport->port_id);
 993                len += scnprintf(buf + len, size - len, "WWPN x%llx ",
 994                                nrport->port_name);
 995                len += scnprintf(buf + len, size - len, "WWNN x%llx ",
 996                                nrport->node_name);
 997
 998                /* An NVME rport can have multiple roles. */
 999                if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR)
1000                        len +=  scnprintf(buf + len, size - len,
1001                                         "INITIATOR ");
1002                if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET)
1003                        len +=  scnprintf(buf + len, size - len,
1004                                         "TARGET ");
1005                if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY)
1006                        len +=  scnprintf(buf + len, size - len,
1007                                         "DISCSRVC ");
1008                if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR |
1009                                          FC_PORT_ROLE_NVME_TARGET |
1010                                          FC_PORT_ROLE_NVME_DISCOVERY))
1011                        len +=  scnprintf(buf + len, size - len,
1012                                         "UNKNOWN ROLE x%x",
1013                                         nrport->port_role);
1014                /* Terminate the string. */
1015                len +=  scnprintf(buf + len, size - len, "\n");
1016        }
1017
1018        spin_unlock_irq(shost->host_lock);
1019 out_exit:
1020        return len;
1021}
1022
1023/**
1024 * lpfc_debugfs_nvmestat_data - Dump target node list to a buffer
1025 * @vport: The vport to gather target node info from.
1026 * @buf: The buffer to dump log into.
1027 * @size: The maximum amount of data to process.
1028 *
1029 * Description:
1030 * This routine dumps the NVME statistics associated with @vport
1031 *
1032 * Return Value:
1033 * This routine returns the amount of bytes that were dumped into @buf and will
1034 * not exceed @size.
1035 **/
1036static int
1037lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size)
1038{
1039        struct lpfc_hba   *phba = vport->phba;
1040        struct lpfc_nvmet_tgtport *tgtp;
1041        struct lpfc_nvmet_rcv_ctx *ctxp, *next_ctxp;
1042        struct nvme_fc_local_port *localport;
1043        struct lpfc_fc4_ctrl_stat *cstat;
1044        struct lpfc_nvme_lport *lport;
1045        uint64_t data1, data2, data3;
1046        uint64_t tot, totin, totout;
1047        int cnt, i;
1048        int len = 0;
1049
1050        if (phba->nvmet_support) {
1051                if (!phba->targetport)
1052                        return len;
1053                tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
1054                len += scnprintf(buf + len, size - len,
1055                                "\nNVME Targetport Statistics\n");
1056
1057                len += scnprintf(buf + len, size - len,
1058                                "LS: Rcv %08x Drop %08x Abort %08x\n",
1059                                atomic_read(&tgtp->rcv_ls_req_in),
1060                                atomic_read(&tgtp->rcv_ls_req_drop),
1061                                atomic_read(&tgtp->xmt_ls_abort));
1062                if (atomic_read(&tgtp->rcv_ls_req_in) !=
1063                    atomic_read(&tgtp->rcv_ls_req_out)) {
1064                        len += scnprintf(buf + len, size - len,
1065                                        "Rcv LS: in %08x != out %08x\n",
1066                                        atomic_read(&tgtp->rcv_ls_req_in),
1067                                        atomic_read(&tgtp->rcv_ls_req_out));
1068                }
1069
1070                len += scnprintf(buf + len, size - len,
1071                                "LS: Xmt %08x Drop %08x Cmpl %08x\n",
1072                                atomic_read(&tgtp->xmt_ls_rsp),
1073                                atomic_read(&tgtp->xmt_ls_drop),
1074                                atomic_read(&tgtp->xmt_ls_rsp_cmpl));
1075
1076                len += scnprintf(buf + len, size - len,
1077                                "LS: RSP Abort %08x xb %08x Err %08x\n",
1078                                atomic_read(&tgtp->xmt_ls_rsp_aborted),
1079                                atomic_read(&tgtp->xmt_ls_rsp_xb_set),
1080                                atomic_read(&tgtp->xmt_ls_rsp_error));
1081
1082                len += scnprintf(buf + len, size - len,
1083                                "FCP: Rcv %08x Defer %08x Release %08x "
1084                                "Drop %08x\n",
1085                                atomic_read(&tgtp->rcv_fcp_cmd_in),
1086                                atomic_read(&tgtp->rcv_fcp_cmd_defer),
1087                                atomic_read(&tgtp->xmt_fcp_release),
1088                                atomic_read(&tgtp->rcv_fcp_cmd_drop));
1089
1090                if (atomic_read(&tgtp->rcv_fcp_cmd_in) !=
1091                    atomic_read(&tgtp->rcv_fcp_cmd_out)) {
1092                        len += scnprintf(buf + len, size - len,
1093                                        "Rcv FCP: in %08x != out %08x\n",
1094                                        atomic_read(&tgtp->rcv_fcp_cmd_in),
1095                                        atomic_read(&tgtp->rcv_fcp_cmd_out));
1096                }
1097
1098                len += scnprintf(buf + len, size - len,
1099                                "FCP Rsp: read %08x readrsp %08x "
1100                                "write %08x rsp %08x\n",
1101                                atomic_read(&tgtp->xmt_fcp_read),
1102                                atomic_read(&tgtp->xmt_fcp_read_rsp),
1103                                atomic_read(&tgtp->xmt_fcp_write),
1104                                atomic_read(&tgtp->xmt_fcp_rsp));
1105
1106                len += scnprintf(buf + len, size - len,
1107                                "FCP Rsp Cmpl: %08x err %08x drop %08x\n",
1108                                atomic_read(&tgtp->xmt_fcp_rsp_cmpl),
1109                                atomic_read(&tgtp->xmt_fcp_rsp_error),
1110                                atomic_read(&tgtp->xmt_fcp_rsp_drop));
1111
1112                len += scnprintf(buf + len, size - len,
1113                                "FCP Rsp Abort: %08x xb %08x xricqe  %08x\n",
1114                                atomic_read(&tgtp->xmt_fcp_rsp_aborted),
1115                                atomic_read(&tgtp->xmt_fcp_rsp_xb_set),
1116                                atomic_read(&tgtp->xmt_fcp_xri_abort_cqe));
1117
1118                len += scnprintf(buf + len, size - len,
1119                                "ABORT: Xmt %08x Cmpl %08x\n",
1120                                atomic_read(&tgtp->xmt_fcp_abort),
1121                                atomic_read(&tgtp->xmt_fcp_abort_cmpl));
1122
1123                len += scnprintf(buf + len, size - len,
1124                                "ABORT: Sol %08x  Usol %08x Err %08x Cmpl %08x",
1125                                atomic_read(&tgtp->xmt_abort_sol),
1126                                atomic_read(&tgtp->xmt_abort_unsol),
1127                                atomic_read(&tgtp->xmt_abort_rsp),
1128                                atomic_read(&tgtp->xmt_abort_rsp_error));
1129
1130                len +=  scnprintf(buf + len, size - len, "\n");
1131
1132                cnt = 0;
1133                spin_lock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
1134                list_for_each_entry_safe(ctxp, next_ctxp,
1135                                &phba->sli4_hba.lpfc_abts_nvmet_ctx_list,
1136                                list) {
1137                        cnt++;
1138                }
1139                spin_unlock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
1140                if (cnt) {
1141                        len += scnprintf(buf + len, size - len,
1142                                        "ABORT: %d ctx entries\n", cnt);
1143                        spin_lock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
1144                        list_for_each_entry_safe(ctxp, next_ctxp,
1145                                    &phba->sli4_hba.lpfc_abts_nvmet_ctx_list,
1146                                    list) {
1147                                if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ))
1148                                        break;
1149                                len += scnprintf(buf + len, size - len,
1150                                                "Entry: oxid %x state %x "
1151                                                "flag %x\n",
1152                                                ctxp->oxid, ctxp->state,
1153                                                ctxp->flag);
1154                        }
1155                        spin_unlock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
1156                }
1157
1158                /* Calculate outstanding IOs */
1159                tot = atomic_read(&tgtp->rcv_fcp_cmd_drop);
1160                tot += atomic_read(&tgtp->xmt_fcp_release);
1161                tot = atomic_read(&tgtp->rcv_fcp_cmd_in) - tot;
1162
1163                len += scnprintf(buf + len, size - len,
1164                                "IO_CTX: %08x  WAIT: cur %08x tot %08x\n"
1165                                "CTX Outstanding %08llx\n",
1166                                phba->sli4_hba.nvmet_xri_cnt,
1167                                phba->sli4_hba.nvmet_io_wait_cnt,
1168                                phba->sli4_hba.nvmet_io_wait_total,
1169                                tot);
1170        } else {
1171                if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_NVME))
1172                        return len;
1173
1174                localport = vport->localport;
1175                if (!localport)
1176                        return len;
1177                lport = (struct lpfc_nvme_lport *)localport->private;
1178                if (!lport)
1179                        return len;
1180
1181                len += scnprintf(buf + len, size - len,
1182                                "\nNVME HDWQ Statistics\n");
1183
1184                len += scnprintf(buf + len, size - len,
1185                                "LS: Xmt %016x Cmpl %016x\n",
1186                                atomic_read(&lport->fc4NvmeLsRequests),
1187                                atomic_read(&lport->fc4NvmeLsCmpls));
1188
1189                totin = 0;
1190                totout = 0;
1191                for (i = 0; i < phba->cfg_hdw_queue; i++) {
1192                        cstat = &phba->sli4_hba.hdwq[i].nvme_cstat;
1193                        tot = cstat->io_cmpls;
1194                        totin += tot;
1195                        data1 = cstat->input_requests;
1196                        data2 = cstat->output_requests;
1197                        data3 = cstat->control_requests;
1198                        totout += (data1 + data2 + data3);
1199
1200                        /* Limit to 32, debugfs display buffer limitation */
1201                        if (i >= 32)
1202                                continue;
1203
1204                        len += scnprintf(buf + len, PAGE_SIZE - len,
1205                                        "HDWQ (%d): Rd %016llx Wr %016llx "
1206                                        "IO %016llx ",
1207                                        i, data1, data2, data3);
1208                        len += scnprintf(buf + len, PAGE_SIZE - len,
1209                                        "Cmpl %016llx OutIO %016llx\n",
1210                                        tot, ((data1 + data2 + data3) - tot));
1211                }
1212                len += scnprintf(buf + len, PAGE_SIZE - len,
1213                                "Total FCP Cmpl %016llx Issue %016llx "
1214                                "OutIO %016llx\n",
1215                                totin, totout, totout - totin);
1216
1217                len += scnprintf(buf + len, size - len,
1218                                "LS Xmt Err: Abrt %08x Err %08x  "
1219                                "Cmpl Err: xb %08x Err %08x\n",
1220                                atomic_read(&lport->xmt_ls_abort),
1221                                atomic_read(&lport->xmt_ls_err),
1222                                atomic_read(&lport->cmpl_ls_xb),
1223                                atomic_read(&lport->cmpl_ls_err));
1224
1225                len += scnprintf(buf + len, size - len,
1226                                "FCP Xmt Err: noxri %06x nondlp %06x "
1227                                "qdepth %06x wqerr %06x err %06x Abrt %06x\n",
1228                                atomic_read(&lport->xmt_fcp_noxri),
1229                                atomic_read(&lport->xmt_fcp_bad_ndlp),
1230                                atomic_read(&lport->xmt_fcp_qdepth),
1231                                atomic_read(&lport->xmt_fcp_wqerr),
1232                                atomic_read(&lport->xmt_fcp_err),
1233                                atomic_read(&lport->xmt_fcp_abort));
1234
1235                len += scnprintf(buf + len, size - len,
1236                                "FCP Cmpl Err: xb %08x Err %08x\n",
1237                                atomic_read(&lport->cmpl_fcp_xb),
1238                                atomic_read(&lport->cmpl_fcp_err));
1239
1240        }
1241
1242        return len;
1243}
1244
1245/**
1246 * lpfc_debugfs_scsistat_data - Dump target node list to a buffer
1247 * @vport: The vport to gather target node info from.
1248 * @buf: The buffer to dump log into.
1249 * @size: The maximum amount of data to process.
1250 *
1251 * Description:
1252 * This routine dumps the SCSI statistics associated with @vport
1253 *
1254 * Return Value:
1255 * This routine returns the amount of bytes that were dumped into @buf and will
1256 * not exceed @size.
1257 **/
1258static int
1259lpfc_debugfs_scsistat_data(struct lpfc_vport *vport, char *buf, int size)
1260{
1261        int len;
1262        struct lpfc_hba *phba = vport->phba;
1263        struct lpfc_fc4_ctrl_stat *cstat;
1264        u64 data1, data2, data3;
1265        u64 tot, totin, totout;
1266        int i;
1267        char tmp[LPFC_MAX_SCSI_INFO_TMP_LEN] = {0};
1268
1269        if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_FCP) ||
1270            (phba->sli_rev != LPFC_SLI_REV4))
1271                return 0;
1272
1273        scnprintf(buf, size, "SCSI HDWQ Statistics\n");
1274
1275        totin = 0;
1276        totout = 0;
1277        for (i = 0; i < phba->cfg_hdw_queue; i++) {
1278                cstat = &phba->sli4_hba.hdwq[i].scsi_cstat;
1279                tot = cstat->io_cmpls;
1280                totin += tot;
1281                data1 = cstat->input_requests;
1282                data2 = cstat->output_requests;
1283                data3 = cstat->control_requests;
1284                totout += (data1 + data2 + data3);
1285
1286                scnprintf(tmp, sizeof(tmp), "HDWQ (%d): Rd %016llx Wr %016llx "
1287                          "IO %016llx ", i, data1, data2, data3);
1288                if (strlcat(buf, tmp, size) >= size)
1289                        goto buffer_done;
1290
1291                scnprintf(tmp, sizeof(tmp), "Cmpl %016llx OutIO %016llx\n",
1292                          tot, ((data1 + data2 + data3) - tot));
1293                if (strlcat(buf, tmp, size) >= size)
1294                        goto buffer_done;
1295        }
1296        scnprintf(tmp, sizeof(tmp), "Total FCP Cmpl %016llx Issue %016llx "
1297                  "OutIO %016llx\n", totin, totout, totout - totin);
1298        strlcat(buf, tmp, size);
1299
1300buffer_done:
1301        len = strnlen(buf, size);
1302
1303        return len;
1304}
1305
1306/**
1307 * lpfc_debugfs_nvmektime_data - Dump target node list to a buffer
1308 * @vport: The vport to gather target node info from.
1309 * @buf: The buffer to dump log into.
1310 * @size: The maximum amount of data to process.
1311 *
1312 * Description:
1313 * This routine dumps the NVME statistics associated with @vport
1314 *
1315 * Return Value:
1316 * This routine returns the amount of bytes that were dumped into @buf and will
1317 * not exceed @size.
1318 **/
1319static int
1320lpfc_debugfs_nvmektime_data(struct lpfc_vport *vport, char *buf, int size)
1321{
1322        struct lpfc_hba   *phba = vport->phba;
1323        int len = 0;
1324
1325        if (phba->nvmet_support == 0) {
1326                /* NVME Initiator */
1327                len += scnprintf(buf + len, PAGE_SIZE - len,
1328                                "ktime %s: Total Samples: %lld\n",
1329                                (phba->ktime_on ?  "Enabled" : "Disabled"),
1330                                phba->ktime_data_samples);
1331                if (phba->ktime_data_samples == 0)
1332                        return len;
1333
1334                len += scnprintf(
1335                        buf + len, PAGE_SIZE - len,
1336                        "Segment 1: Last NVME Cmd cmpl "
1337                        "done -to- Start of next NVME cnd (in driver)\n");
1338                len += scnprintf(
1339                        buf + len, PAGE_SIZE - len,
1340                        "avg:%08lld min:%08lld max %08lld\n",
1341                        div_u64(phba->ktime_seg1_total,
1342                                phba->ktime_data_samples),
1343                        phba->ktime_seg1_min,
1344                        phba->ktime_seg1_max);
1345                len += scnprintf(
1346                        buf + len, PAGE_SIZE - len,
1347                        "Segment 2: Driver start of NVME cmd "
1348                        "-to- Firmware WQ doorbell\n");
1349                len += scnprintf(
1350                        buf + len, PAGE_SIZE - len,
1351                        "avg:%08lld min:%08lld max %08lld\n",
1352                        div_u64(phba->ktime_seg2_total,
1353                                phba->ktime_data_samples),
1354                        phba->ktime_seg2_min,
1355                        phba->ktime_seg2_max);
1356                len += scnprintf(
1357                        buf + len, PAGE_SIZE - len,
1358                        "Segment 3: Firmware WQ doorbell -to- "
1359                        "MSI-X ISR cmpl\n");
1360                len += scnprintf(
1361                        buf + len, PAGE_SIZE - len,
1362                        "avg:%08lld min:%08lld max %08lld\n",
1363                        div_u64(phba->ktime_seg3_total,
1364                                phba->ktime_data_samples),
1365                        phba->ktime_seg3_min,
1366                        phba->ktime_seg3_max);
1367                len += scnprintf(
1368                        buf + len, PAGE_SIZE - len,
1369                        "Segment 4: MSI-X ISR cmpl -to- "
1370                        "NVME cmpl done\n");
1371                len += scnprintf(
1372                        buf + len, PAGE_SIZE - len,
1373                        "avg:%08lld min:%08lld max %08lld\n",
1374                        div_u64(phba->ktime_seg4_total,
1375                                phba->ktime_data_samples),
1376                        phba->ktime_seg4_min,
1377                        phba->ktime_seg4_max);
1378                len += scnprintf(
1379                        buf + len, PAGE_SIZE - len,
1380                        "Total IO avg time: %08lld\n",
1381                        div_u64(phba->ktime_seg1_total +
1382                        phba->ktime_seg2_total  +
1383                        phba->ktime_seg3_total +
1384                        phba->ktime_seg4_total,
1385                        phba->ktime_data_samples));
1386                return len;
1387        }
1388
1389        /* NVME Target */
1390        len += scnprintf(buf + len, PAGE_SIZE-len,
1391                        "ktime %s: Total Samples: %lld %lld\n",
1392                        (phba->ktime_on ? "Enabled" : "Disabled"),
1393                        phba->ktime_data_samples,
1394                        phba->ktime_status_samples);
1395        if (phba->ktime_data_samples == 0)
1396                return len;
1397
1398        len += scnprintf(buf + len, PAGE_SIZE-len,
1399                        "Segment 1: MSI-X ISR Rcv cmd -to- "
1400                        "cmd pass to NVME Layer\n");
1401        len += scnprintf(buf + len, PAGE_SIZE-len,
1402                        "avg:%08lld min:%08lld max %08lld\n",
1403                        div_u64(phba->ktime_seg1_total,
1404                                phba->ktime_data_samples),
1405                        phba->ktime_seg1_min,
1406                        phba->ktime_seg1_max);
1407        len += scnprintf(buf + len, PAGE_SIZE-len,
1408                        "Segment 2: cmd pass to NVME Layer- "
1409                        "-to- Driver rcv cmd OP (action)\n");
1410        len += scnprintf(buf + len, PAGE_SIZE-len,
1411                        "avg:%08lld min:%08lld max %08lld\n",
1412                        div_u64(phba->ktime_seg2_total,
1413                                phba->ktime_data_samples),
1414                        phba->ktime_seg2_min,
1415                        phba->ktime_seg2_max);
1416        len += scnprintf(buf + len, PAGE_SIZE-len,
1417                        "Segment 3: Driver rcv cmd OP -to- "
1418                        "Firmware WQ doorbell: cmd\n");
1419        len += scnprintf(buf + len, PAGE_SIZE-len,
1420                        "avg:%08lld min:%08lld max %08lld\n",
1421                        div_u64(phba->ktime_seg3_total,
1422                                phba->ktime_data_samples),
1423                        phba->ktime_seg3_min,
1424                        phba->ktime_seg3_max);
1425        len += scnprintf(buf + len, PAGE_SIZE-len,
1426                        "Segment 4: Firmware WQ doorbell: cmd "
1427                        "-to- MSI-X ISR for cmd cmpl\n");
1428        len += scnprintf(buf + len, PAGE_SIZE-len,
1429                        "avg:%08lld min:%08lld max %08lld\n",
1430                        div_u64(phba->ktime_seg4_total,
1431                                phba->ktime_data_samples),
1432                        phba->ktime_seg4_min,
1433                        phba->ktime_seg4_max);
1434        len += scnprintf(buf + len, PAGE_SIZE-len,
1435                        "Segment 5: MSI-X ISR for cmd cmpl "
1436                        "-to- NVME layer passed cmd done\n");
1437        len += scnprintf(buf + len, PAGE_SIZE-len,
1438                        "avg:%08lld min:%08lld max %08lld\n",
1439                        div_u64(phba->ktime_seg5_total,
1440                                phba->ktime_data_samples),
1441                        phba->ktime_seg5_min,
1442                        phba->ktime_seg5_max);
1443
1444        if (phba->ktime_status_samples == 0) {
1445                len += scnprintf(buf + len, PAGE_SIZE-len,
1446                                "Total: cmd received by MSI-X ISR "
1447                                "-to- cmd completed on wire\n");
1448                len += scnprintf(buf + len, PAGE_SIZE-len,
1449                                "avg:%08lld min:%08lld "
1450                                "max %08lld\n",
1451                                div_u64(phba->ktime_seg10_total,
1452                                        phba->ktime_data_samples),
1453                                phba->ktime_seg10_min,
1454                                phba->ktime_seg10_max);
1455                return len;
1456        }
1457
1458        len += scnprintf(buf + len, PAGE_SIZE-len,
1459                        "Segment 6: NVME layer passed cmd done "
1460                        "-to- Driver rcv rsp status OP\n");
1461        len += scnprintf(buf + len, PAGE_SIZE-len,
1462                        "avg:%08lld min:%08lld max %08lld\n",
1463                        div_u64(phba->ktime_seg6_total,
1464                                phba->ktime_status_samples),
1465                        phba->ktime_seg6_min,
1466                        phba->ktime_seg6_max);
1467        len += scnprintf(buf + len, PAGE_SIZE-len,
1468                        "Segment 7: Driver rcv rsp status OP "
1469                        "-to- Firmware WQ doorbell: status\n");
1470        len += scnprintf(buf + len, PAGE_SIZE-len,
1471                        "avg:%08lld min:%08lld max %08lld\n",
1472                        div_u64(phba->ktime_seg7_total,
1473                                phba->ktime_status_samples),
1474                        phba->ktime_seg7_min,
1475                        phba->ktime_seg7_max);
1476        len += scnprintf(buf + len, PAGE_SIZE-len,
1477                        "Segment 8: Firmware WQ doorbell: status"
1478                        " -to- MSI-X ISR for status cmpl\n");
1479        len += scnprintf(buf + len, PAGE_SIZE-len,
1480                        "avg:%08lld min:%08lld max %08lld\n",
1481                        div_u64(phba->ktime_seg8_total,
1482                                phba->ktime_status_samples),
1483                        phba->ktime_seg8_min,
1484                        phba->ktime_seg8_max);
1485        len += scnprintf(buf + len, PAGE_SIZE-len,
1486                        "Segment 9: MSI-X ISR for status cmpl  "
1487                        "-to- NVME layer passed status done\n");
1488        len += scnprintf(buf + len, PAGE_SIZE-len,
1489                        "avg:%08lld min:%08lld max %08lld\n",
1490                        div_u64(phba->ktime_seg9_total,
1491                                phba->ktime_status_samples),
1492                        phba->ktime_seg9_min,
1493                        phba->ktime_seg9_max);
1494        len += scnprintf(buf + len, PAGE_SIZE-len,
1495                        "Total: cmd received by MSI-X ISR -to- "
1496                        "cmd completed on wire\n");
1497        len += scnprintf(buf + len, PAGE_SIZE-len,
1498                        "avg:%08lld min:%08lld max %08lld\n",
1499                        div_u64(phba->ktime_seg10_total,
1500                                phba->ktime_status_samples),
1501                        phba->ktime_seg10_min,
1502                        phba->ktime_seg10_max);
1503        return len;
1504}
1505
1506/**
1507 * lpfc_debugfs_nvmeio_trc_data - Dump NVME IO trace list to a buffer
1508 * @phba: The phba to gather target node info from.
1509 * @buf: The buffer to dump log into.
1510 * @size: The maximum amount of data to process.
1511 *
1512 * Description:
1513 * This routine dumps the NVME IO trace associated with @phba
1514 *
1515 * Return Value:
1516 * This routine returns the amount of bytes that were dumped into @buf and will
1517 * not exceed @size.
1518 **/
1519static int
1520lpfc_debugfs_nvmeio_trc_data(struct lpfc_hba *phba, char *buf, int size)
1521{
1522        struct lpfc_debugfs_nvmeio_trc *dtp;
1523        int i, state, index, skip;
1524        int len = 0;
1525
1526        state = phba->nvmeio_trc_on;
1527
1528        index = (atomic_read(&phba->nvmeio_trc_cnt) + 1) &
1529                (phba->nvmeio_trc_size - 1);
1530        skip = phba->nvmeio_trc_output_idx;
1531
1532        len += scnprintf(buf + len, size - len,
1533                        "%s IO Trace %s: next_idx %d skip %d size %d\n",
1534                        (phba->nvmet_support ? "NVME" : "NVMET"),
1535                        (state ? "Enabled" : "Disabled"),
1536                        index, skip, phba->nvmeio_trc_size);
1537
1538        if (!phba->nvmeio_trc || state)
1539                return len;
1540
1541        /* trace MUST bhe off to continue */
1542
1543        for (i = index; i < phba->nvmeio_trc_size; i++) {
1544                if (skip) {
1545                        skip--;
1546                        continue;
1547                }
1548                dtp = phba->nvmeio_trc + i;
1549                phba->nvmeio_trc_output_idx++;
1550
1551                if (!dtp->fmt)
1552                        continue;
1553
1554                len +=  scnprintf(buf + len, size - len, dtp->fmt,
1555                        dtp->data1, dtp->data2, dtp->data3);
1556
1557                if (phba->nvmeio_trc_output_idx >= phba->nvmeio_trc_size) {
1558                        phba->nvmeio_trc_output_idx = 0;
1559                        len += scnprintf(buf + len, size - len,
1560                                        "Trace Complete\n");
1561                        goto out;
1562                }
1563
1564                if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ)) {
1565                        len += scnprintf(buf + len, size - len,
1566                                        "Trace Continue (%d of %d)\n",
1567                                        phba->nvmeio_trc_output_idx,
1568                                        phba->nvmeio_trc_size);
1569                        goto out;
1570                }
1571        }
1572        for (i = 0; i < index; i++) {
1573                if (skip) {
1574                        skip--;
1575                        continue;
1576                }
1577                dtp = phba->nvmeio_trc + i;
1578                phba->nvmeio_trc_output_idx++;
1579
1580                if (!dtp->fmt)
1581                        continue;
1582
1583                len +=  scnprintf(buf + len, size - len, dtp->fmt,
1584                        dtp->data1, dtp->data2, dtp->data3);
1585
1586                if (phba->nvmeio_trc_output_idx >= phba->nvmeio_trc_size) {
1587                        phba->nvmeio_trc_output_idx = 0;
1588                        len += scnprintf(buf + len, size - len,
1589                                        "Trace Complete\n");
1590                        goto out;
1591                }
1592
1593                if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ)) {
1594                        len += scnprintf(buf + len, size - len,
1595                                        "Trace Continue (%d of %d)\n",
1596                                        phba->nvmeio_trc_output_idx,
1597                                        phba->nvmeio_trc_size);
1598                        goto out;
1599                }
1600        }
1601
1602        len += scnprintf(buf + len, size - len,
1603                        "Trace Done\n");
1604out:
1605        return len;
1606}
1607
1608/**
1609 * lpfc_debugfs_cpucheck_data - Dump target node list to a buffer
1610 * @vport: The vport to gather target node info from.
1611 * @buf: The buffer to dump log into.
1612 * @size: The maximum amount of data to process.
1613 *
1614 * Description:
1615 * This routine dumps the NVME statistics associated with @vport
1616 *
1617 * Return Value:
1618 * This routine returns the amount of bytes that were dumped into @buf and will
1619 * not exceed @size.
1620 **/
1621static int
1622lpfc_debugfs_cpucheck_data(struct lpfc_vport *vport, char *buf, int size)
1623{
1624        struct lpfc_hba   *phba = vport->phba;
1625        struct lpfc_sli4_hdw_queue *qp;
1626        int i, j, max_cnt;
1627        int len = 0;
1628        uint32_t tot_xmt;
1629        uint32_t tot_rcv;
1630        uint32_t tot_cmpl;
1631
1632        len += scnprintf(buf + len, PAGE_SIZE - len,
1633                        "CPUcheck %s ",
1634                        (phba->cpucheck_on & LPFC_CHECK_NVME_IO ?
1635                                "Enabled" : "Disabled"));
1636        if (phba->nvmet_support) {
1637                len += scnprintf(buf + len, PAGE_SIZE - len,
1638                                "%s\n",
1639                                (phba->cpucheck_on & LPFC_CHECK_NVMET_RCV ?
1640                                        "Rcv Enabled\n" : "Rcv Disabled\n"));
1641        } else {
1642                len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
1643        }
1644        max_cnt = size - LPFC_DEBUG_OUT_LINE_SZ;
1645
1646        for (i = 0; i < phba->cfg_hdw_queue; i++) {
1647                qp = &phba->sli4_hba.hdwq[i];
1648
1649                tot_rcv = 0;
1650                tot_xmt = 0;
1651                tot_cmpl = 0;
1652                for (j = 0; j < LPFC_CHECK_CPU_CNT; j++) {
1653                        tot_xmt += qp->cpucheck_xmt_io[j];
1654                        tot_cmpl += qp->cpucheck_cmpl_io[j];
1655                        if (phba->nvmet_support)
1656                                tot_rcv += qp->cpucheck_rcv_io[j];
1657                }
1658
1659                /* Only display Hardware Qs with something */
1660                if (!tot_xmt && !tot_cmpl && !tot_rcv)
1661                        continue;
1662
1663                len += scnprintf(buf + len, PAGE_SIZE - len,
1664                                "HDWQ %03d: ", i);
1665                for (j = 0; j < LPFC_CHECK_CPU_CNT; j++) {
1666                        /* Only display non-zero counters */
1667                        if (!qp->cpucheck_xmt_io[j] &&
1668                            !qp->cpucheck_cmpl_io[j] &&
1669                            !qp->cpucheck_rcv_io[j])
1670                                continue;
1671                        if (phba->nvmet_support) {
1672                                len += scnprintf(buf + len, PAGE_SIZE - len,
1673                                                "CPU %03d: %x/%x/%x ", j,
1674                                                qp->cpucheck_rcv_io[j],
1675                                                qp->cpucheck_xmt_io[j],
1676                                                qp->cpucheck_cmpl_io[j]);
1677                        } else {
1678                                len += scnprintf(buf + len, PAGE_SIZE - len,
1679                                                "CPU %03d: %x/%x ", j,
1680                                                qp->cpucheck_xmt_io[j],
1681                                                qp->cpucheck_cmpl_io[j]);
1682                        }
1683                }
1684                len += scnprintf(buf + len, PAGE_SIZE - len,
1685                                "Total: %x\n", tot_xmt);
1686                if (len >= max_cnt) {
1687                        len += scnprintf(buf + len, PAGE_SIZE - len,
1688                                        "Truncated ...\n");
1689                        return len;
1690                }
1691        }
1692        return len;
1693}
1694
1695#endif
1696
1697/**
1698 * lpfc_debugfs_disc_trc - Store discovery trace log
1699 * @vport: The vport to associate this trace string with for retrieval.
1700 * @mask: Log entry classification.
1701 * @fmt: Format string to be displayed when dumping the log.
1702 * @data1: 1st data parameter to be applied to @fmt.
1703 * @data2: 2nd data parameter to be applied to @fmt.
1704 * @data3: 3rd data parameter to be applied to @fmt.
1705 *
1706 * Description:
1707 * This routine is used by the driver code to add a debugfs log entry to the
1708 * discovery trace buffer associated with @vport. Only entries with a @mask that
1709 * match the current debugfs discovery mask will be saved. Entries that do not
1710 * match will be thrown away. @fmt, @data1, @data2, and @data3 are used like
1711 * printf when displaying the log.
1712 **/
1713inline void
1714lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt,
1715        uint32_t data1, uint32_t data2, uint32_t data3)
1716{
1717#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
1718        struct lpfc_debugfs_trc *dtp;
1719        int index;
1720
1721        if (!(lpfc_debugfs_mask_disc_trc & mask))
1722                return;
1723
1724        if (!lpfc_debugfs_enable || !lpfc_debugfs_max_disc_trc ||
1725                !vport || !vport->disc_trc)
1726                return;
1727
1728        index = atomic_inc_return(&vport->disc_trc_cnt) &
1729                (lpfc_debugfs_max_disc_trc - 1);
1730        dtp = vport->disc_trc + index;
1731        dtp->fmt = fmt;
1732        dtp->data1 = data1;
1733        dtp->data2 = data2;
1734        dtp->data3 = data3;
1735        dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt);
1736        dtp->jif = jiffies;
1737#endif
1738        return;
1739}
1740
1741/**
1742 * lpfc_debugfs_slow_ring_trc - Store slow ring trace log
1743 * @phba: The phba to associate this trace string with for retrieval.
1744 * @fmt: Format string to be displayed when dumping the log.
1745 * @data1: 1st data parameter to be applied to @fmt.
1746 * @data2: 2nd data parameter to be applied to @fmt.
1747 * @data3: 3rd data parameter to be applied to @fmt.
1748 *
1749 * Description:
1750 * This routine is used by the driver code to add a debugfs log entry to the
1751 * discovery trace buffer associated with @vport. @fmt, @data1, @data2, and
1752 * @data3 are used like printf when displaying the log.
1753 **/
1754inline void
1755lpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt,
1756        uint32_t data1, uint32_t data2, uint32_t data3)
1757{
1758#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
1759        struct lpfc_debugfs_trc *dtp;
1760        int index;
1761
1762        if (!lpfc_debugfs_enable || !lpfc_debugfs_max_slow_ring_trc ||
1763                !phba || !phba->slow_ring_trc)
1764                return;
1765
1766        index = atomic_inc_return(&phba->slow_ring_trc_cnt) &
1767                (lpfc_debugfs_max_slow_ring_trc - 1);
1768        dtp = phba->slow_ring_trc + index;
1769        dtp->fmt = fmt;
1770        dtp->data1 = data1;
1771        dtp->data2 = data2;
1772        dtp->data3 = data3;
1773        dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt);
1774        dtp->jif = jiffies;
1775#endif
1776        return;
1777}
1778
1779/**
1780 * lpfc_debugfs_nvme_trc - Store NVME/NVMET trace log
1781 * @phba: The phba to associate this trace string with for retrieval.
1782 * @fmt: Format string to be displayed when dumping the log.
1783 * @data1: 1st data parameter to be applied to @fmt.
1784 * @data2: 2nd data parameter to be applied to @fmt.
1785 * @data3: 3rd data parameter to be applied to @fmt.
1786 *
1787 * Description:
1788 * This routine is used by the driver code to add a debugfs log entry to the
1789 * nvme trace buffer associated with @phba. @fmt, @data1, @data2, and
1790 * @data3 are used like printf when displaying the log.
1791 **/
1792inline void
1793lpfc_debugfs_nvme_trc(struct lpfc_hba *phba, char *fmt,
1794                      uint16_t data1, uint16_t data2, uint32_t data3)
1795{
1796#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
1797        struct lpfc_debugfs_nvmeio_trc *dtp;
1798        int index;
1799
1800        if (!phba->nvmeio_trc_on || !phba->nvmeio_trc)
1801                return;
1802
1803        index = atomic_inc_return(&phba->nvmeio_trc_cnt) &
1804                (phba->nvmeio_trc_size - 1);
1805        dtp = phba->nvmeio_trc + index;
1806        dtp->fmt = fmt;
1807        dtp->data1 = data1;
1808        dtp->data2 = data2;
1809        dtp->data3 = data3;
1810#endif
1811}
1812
1813#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
1814/**
1815 * lpfc_debugfs_disc_trc_open - Open the discovery trace log
1816 * @inode: The inode pointer that contains a vport pointer.
1817 * @file: The file pointer to attach the log output.
1818 *
1819 * Description:
1820 * This routine is the entry point for the debugfs open file operation. It gets
1821 * the vport from the i_private field in @inode, allocates the necessary buffer
1822 * for the log, fills the buffer from the in-memory log for this vport, and then
1823 * returns a pointer to that log in the private_data field in @file.
1824 *
1825 * Returns:
1826 * This function returns zero if successful. On error it will return a negative
1827 * error value.
1828 **/
1829static int
1830lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file)
1831{
1832        struct lpfc_vport *vport = inode->i_private;
1833        struct lpfc_debug *debug;
1834        int size;
1835        int rc = -ENOMEM;
1836
1837        if (!lpfc_debugfs_max_disc_trc) {
1838                rc = -ENOSPC;
1839                goto out;
1840        }
1841
1842        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
1843        if (!debug)
1844                goto out;
1845
1846        /* Round to page boundary */
1847        size =  (lpfc_debugfs_max_disc_trc * LPFC_DEBUG_TRC_ENTRY_SIZE);
1848        size = PAGE_ALIGN(size);
1849
1850        debug->buffer = kmalloc(size, GFP_KERNEL);
1851        if (!debug->buffer) {
1852                kfree(debug);
1853                goto out;
1854        }
1855
1856        debug->len = lpfc_debugfs_disc_trc_data(vport, debug->buffer, size);
1857        file->private_data = debug;
1858
1859        rc = 0;
1860out:
1861        return rc;
1862}
1863
1864/**
1865 * lpfc_debugfs_slow_ring_trc_open - Open the Slow Ring trace log
1866 * @inode: The inode pointer that contains a vport pointer.
1867 * @file: The file pointer to attach the log output.
1868 *
1869 * Description:
1870 * This routine is the entry point for the debugfs open file operation. It gets
1871 * the vport from the i_private field in @inode, allocates the necessary buffer
1872 * for the log, fills the buffer from the in-memory log for this vport, and then
1873 * returns a pointer to that log in the private_data field in @file.
1874 *
1875 * Returns:
1876 * This function returns zero if successful. On error it will return a negative
1877 * error value.
1878 **/
1879static int
1880lpfc_debugfs_slow_ring_trc_open(struct inode *inode, struct file *file)
1881{
1882        struct lpfc_hba *phba = inode->i_private;
1883        struct lpfc_debug *debug;
1884        int size;
1885        int rc = -ENOMEM;
1886
1887        if (!lpfc_debugfs_max_slow_ring_trc) {
1888                rc = -ENOSPC;
1889                goto out;
1890        }
1891
1892        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
1893        if (!debug)
1894                goto out;
1895
1896        /* Round to page boundary */
1897        size =  (lpfc_debugfs_max_slow_ring_trc * LPFC_DEBUG_TRC_ENTRY_SIZE);
1898        size = PAGE_ALIGN(size);
1899
1900        debug->buffer = kmalloc(size, GFP_KERNEL);
1901        if (!debug->buffer) {
1902                kfree(debug);
1903                goto out;
1904        }
1905
1906        debug->len = lpfc_debugfs_slow_ring_trc_data(phba, debug->buffer, size);
1907        file->private_data = debug;
1908
1909        rc = 0;
1910out:
1911        return rc;
1912}
1913
1914/**
1915 * lpfc_debugfs_hbqinfo_open - Open the hbqinfo debugfs buffer
1916 * @inode: The inode pointer that contains a vport pointer.
1917 * @file: The file pointer to attach the log output.
1918 *
1919 * Description:
1920 * This routine is the entry point for the debugfs open file operation. It gets
1921 * the vport from the i_private field in @inode, allocates the necessary buffer
1922 * for the log, fills the buffer from the in-memory log for this vport, and then
1923 * returns a pointer to that log in the private_data field in @file.
1924 *
1925 * Returns:
1926 * This function returns zero if successful. On error it will return a negative
1927 * error value.
1928 **/
1929static int
1930lpfc_debugfs_hbqinfo_open(struct inode *inode, struct file *file)
1931{
1932        struct lpfc_hba *phba = inode->i_private;
1933        struct lpfc_debug *debug;
1934        int rc = -ENOMEM;
1935
1936        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
1937        if (!debug)
1938                goto out;
1939
1940        /* Round to page boundary */
1941        debug->buffer = kmalloc(LPFC_HBQINFO_SIZE, GFP_KERNEL);
1942        if (!debug->buffer) {
1943                kfree(debug);
1944                goto out;
1945        }
1946
1947        debug->len = lpfc_debugfs_hbqinfo_data(phba, debug->buffer,
1948                LPFC_HBQINFO_SIZE);
1949        file->private_data = debug;
1950
1951        rc = 0;
1952out:
1953        return rc;
1954}
1955
1956/**
1957 * lpfc_debugfs_multixripools_open - Open the multixripool debugfs buffer
1958 * @inode: The inode pointer that contains a hba pointer.
1959 * @file: The file pointer to attach the log output.
1960 *
1961 * Description:
1962 * This routine is the entry point for the debugfs open file operation. It gets
1963 * the hba from the i_private field in @inode, allocates the necessary buffer
1964 * for the log, fills the buffer from the in-memory log for this hba, and then
1965 * returns a pointer to that log in the private_data field in @file.
1966 *
1967 * Returns:
1968 * This function returns zero if successful. On error it will return a negative
1969 * error value.
1970 **/
1971static int
1972lpfc_debugfs_multixripools_open(struct inode *inode, struct file *file)
1973{
1974        struct lpfc_hba *phba = inode->i_private;
1975        struct lpfc_debug *debug;
1976        int rc = -ENOMEM;
1977
1978        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
1979        if (!debug)
1980                goto out;
1981
1982        /* Round to page boundary */
1983        debug->buffer = kzalloc(LPFC_DUMP_MULTIXRIPOOL_SIZE, GFP_KERNEL);
1984        if (!debug->buffer) {
1985                kfree(debug);
1986                goto out;
1987        }
1988
1989        debug->len = lpfc_debugfs_multixripools_data(
1990                phba, debug->buffer, LPFC_DUMP_MULTIXRIPOOL_SIZE);
1991
1992        debug->i_private = inode->i_private;
1993        file->private_data = debug;
1994
1995        rc = 0;
1996out:
1997        return rc;
1998}
1999
2000#ifdef LPFC_HDWQ_LOCK_STAT
2001/**
2002 * lpfc_debugfs_lockstat_open - Open the lockstat debugfs buffer
2003 * @inode: The inode pointer that contains a vport pointer.
2004 * @file: The file pointer to attach the log output.
2005 *
2006 * Description:
2007 * This routine is the entry point for the debugfs open file operation. It gets
2008 * the vport from the i_private field in @inode, allocates the necessary buffer
2009 * for the log, fills the buffer from the in-memory log for this vport, and then
2010 * returns a pointer to that log in the private_data field in @file.
2011 *
2012 * Returns:
2013 * This function returns zero if successful. On error it will return a negative
2014 * error value.
2015 **/
2016static int
2017lpfc_debugfs_lockstat_open(struct inode *inode, struct file *file)
2018{
2019        struct lpfc_hba *phba = inode->i_private;
2020        struct lpfc_debug *debug;
2021        int rc = -ENOMEM;
2022
2023        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2024        if (!debug)
2025                goto out;
2026
2027        /* Round to page boundary */
2028        debug->buffer = kmalloc(LPFC_HDWQINFO_SIZE, GFP_KERNEL);
2029        if (!debug->buffer) {
2030                kfree(debug);
2031                goto out;
2032        }
2033
2034        debug->len = lpfc_debugfs_lockstat_data(phba, debug->buffer,
2035                LPFC_HBQINFO_SIZE);
2036        file->private_data = debug;
2037
2038        rc = 0;
2039out:
2040        return rc;
2041}
2042
2043static ssize_t
2044lpfc_debugfs_lockstat_write(struct file *file, const char __user *buf,
2045                            size_t nbytes, loff_t *ppos)
2046{
2047        struct lpfc_debug *debug = file->private_data;
2048        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
2049        struct lpfc_sli4_hdw_queue *qp;
2050        char mybuf[64];
2051        char *pbuf;
2052        int i;
2053
2054        /* Protect copy from user */
2055        if (!access_ok(buf, nbytes))
2056                return -EFAULT;
2057
2058        memset(mybuf, 0, sizeof(mybuf));
2059
2060        if (copy_from_user(mybuf, buf, nbytes))
2061                return -EFAULT;
2062        pbuf = &mybuf[0];
2063
2064        if ((strncmp(pbuf, "reset", strlen("reset")) == 0) ||
2065            (strncmp(pbuf, "zero", strlen("zero")) == 0)) {
2066                for (i = 0; i < phba->cfg_hdw_queue; i++) {
2067                        qp = &phba->sli4_hba.hdwq[i];
2068                        qp->lock_conflict.alloc_xri_get = 0;
2069                        qp->lock_conflict.alloc_xri_put = 0;
2070                        qp->lock_conflict.free_xri = 0;
2071                        qp->lock_conflict.wq_access = 0;
2072                        qp->lock_conflict.alloc_pvt_pool = 0;
2073                        qp->lock_conflict.mv_from_pvt_pool = 0;
2074                        qp->lock_conflict.mv_to_pub_pool = 0;
2075                        qp->lock_conflict.mv_to_pvt_pool = 0;
2076                        qp->lock_conflict.free_pvt_pool = 0;
2077                        qp->lock_conflict.free_pub_pool = 0;
2078                        qp->lock_conflict.wq_access = 0;
2079                }
2080        }
2081        return nbytes;
2082}
2083#endif
2084
2085/**
2086 * lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer
2087 * @inode: The inode pointer that contains a vport pointer.
2088 * @file: The file pointer to attach the log output.
2089 *
2090 * Description:
2091 * This routine is the entry point for the debugfs open file operation. It gets
2092 * the vport from the i_private field in @inode, allocates the necessary buffer
2093 * for the log, fills the buffer from the in-memory log for this vport, and then
2094 * returns a pointer to that log in the private_data field in @file.
2095 *
2096 * Returns:
2097 * This function returns zero if successful. On error it will return a negative
2098 * error value.
2099 **/
2100static int
2101lpfc_debugfs_dumpHBASlim_open(struct inode *inode, struct file *file)
2102{
2103        struct lpfc_hba *phba = inode->i_private;
2104        struct lpfc_debug *debug;
2105        int rc = -ENOMEM;
2106
2107        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2108        if (!debug)
2109                goto out;
2110
2111        /* Round to page boundary */
2112        debug->buffer = kmalloc(LPFC_DUMPHBASLIM_SIZE, GFP_KERNEL);
2113        if (!debug->buffer) {
2114                kfree(debug);
2115                goto out;
2116        }
2117
2118        debug->len = lpfc_debugfs_dumpHBASlim_data(phba, debug->buffer,
2119                LPFC_DUMPHBASLIM_SIZE);
2120        file->private_data = debug;
2121
2122        rc = 0;
2123out:
2124        return rc;
2125}
2126
2127/**
2128 * lpfc_debugfs_dumpHostSlim_open - Open the Dump Host SLIM debugfs buffer
2129 * @inode: The inode pointer that contains a vport pointer.
2130 * @file: The file pointer to attach the log output.
2131 *
2132 * Description:
2133 * This routine is the entry point for the debugfs open file operation. It gets
2134 * the vport from the i_private field in @inode, allocates the necessary buffer
2135 * for the log, fills the buffer from the in-memory log for this vport, and then
2136 * returns a pointer to that log in the private_data field in @file.
2137 *
2138 * Returns:
2139 * This function returns zero if successful. On error it will return a negative
2140 * error value.
2141 **/
2142static int
2143lpfc_debugfs_dumpHostSlim_open(struct inode *inode, struct file *file)
2144{
2145        struct lpfc_hba *phba = inode->i_private;
2146        struct lpfc_debug *debug;
2147        int rc = -ENOMEM;
2148
2149        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2150        if (!debug)
2151                goto out;
2152
2153        /* Round to page boundary */
2154        debug->buffer = kmalloc(LPFC_DUMPHOSTSLIM_SIZE, GFP_KERNEL);
2155        if (!debug->buffer) {
2156                kfree(debug);
2157                goto out;
2158        }
2159
2160        debug->len = lpfc_debugfs_dumpHostSlim_data(phba, debug->buffer,
2161                LPFC_DUMPHOSTSLIM_SIZE);
2162        file->private_data = debug;
2163
2164        rc = 0;
2165out:
2166        return rc;
2167}
2168
2169static int
2170lpfc_debugfs_dumpData_open(struct inode *inode, struct file *file)
2171{
2172        struct lpfc_debug *debug;
2173        int rc = -ENOMEM;
2174
2175        if (!_dump_buf_data)
2176                return -EBUSY;
2177
2178        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2179        if (!debug)
2180                goto out;
2181
2182        /* Round to page boundary */
2183        pr_err("9059 BLKGRD:  %s: _dump_buf_data=0x%p\n",
2184                        __func__, _dump_buf_data);
2185        debug->buffer = _dump_buf_data;
2186        if (!debug->buffer) {
2187                kfree(debug);
2188                goto out;
2189        }
2190
2191        debug->len = (1 << _dump_buf_data_order) << PAGE_SHIFT;
2192        file->private_data = debug;
2193
2194        rc = 0;
2195out:
2196        return rc;
2197}
2198
2199static int
2200lpfc_debugfs_dumpDif_open(struct inode *inode, struct file *file)
2201{
2202        struct lpfc_debug *debug;
2203        int rc = -ENOMEM;
2204
2205        if (!_dump_buf_dif)
2206                return -EBUSY;
2207
2208        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2209        if (!debug)
2210                goto out;
2211
2212        /* Round to page boundary */
2213        pr_err("9060 BLKGRD: %s: _dump_buf_dif=0x%p file=%pD\n",
2214                        __func__, _dump_buf_dif, file);
2215        debug->buffer = _dump_buf_dif;
2216        if (!debug->buffer) {
2217                kfree(debug);
2218                goto out;
2219        }
2220
2221        debug->len = (1 << _dump_buf_dif_order) << PAGE_SHIFT;
2222        file->private_data = debug;
2223
2224        rc = 0;
2225out:
2226        return rc;
2227}
2228
2229static ssize_t
2230lpfc_debugfs_dumpDataDif_write(struct file *file, const char __user *buf,
2231                  size_t nbytes, loff_t *ppos)
2232{
2233        /*
2234         * The Data/DIF buffers only save one failing IO
2235         * The write op is used as a reset mechanism after an IO has
2236         * already been saved to the next one can be saved
2237         */
2238        spin_lock(&_dump_buf_lock);
2239
2240        memset((void *)_dump_buf_data, 0,
2241                        ((1 << PAGE_SHIFT) << _dump_buf_data_order));
2242        memset((void *)_dump_buf_dif, 0,
2243                        ((1 << PAGE_SHIFT) << _dump_buf_dif_order));
2244
2245        _dump_buf_done = 0;
2246
2247        spin_unlock(&_dump_buf_lock);
2248
2249        return nbytes;
2250}
2251
2252static ssize_t
2253lpfc_debugfs_dif_err_read(struct file *file, char __user *buf,
2254        size_t nbytes, loff_t *ppos)
2255{
2256        struct dentry *dent = file->f_path.dentry;
2257        struct lpfc_hba *phba = file->private_data;
2258        char cbuf[32];
2259        uint64_t tmp = 0;
2260        int cnt = 0;
2261
2262        if (dent == phba->debug_writeGuard)
2263                cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wgrd_cnt);
2264        else if (dent == phba->debug_writeApp)
2265                cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wapp_cnt);
2266        else if (dent == phba->debug_writeRef)
2267                cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wref_cnt);
2268        else if (dent == phba->debug_readGuard)
2269                cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rgrd_cnt);
2270        else if (dent == phba->debug_readApp)
2271                cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rapp_cnt);
2272        else if (dent == phba->debug_readRef)
2273                cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rref_cnt);
2274        else if (dent == phba->debug_InjErrNPortID)
2275                cnt = scnprintf(cbuf, 32, "0x%06x\n",
2276                                phba->lpfc_injerr_nportid);
2277        else if (dent == phba->debug_InjErrWWPN) {
2278                memcpy(&tmp, &phba->lpfc_injerr_wwpn, sizeof(struct lpfc_name));
2279                tmp = cpu_to_be64(tmp);
2280                cnt = scnprintf(cbuf, 32, "0x%016llx\n", tmp);
2281        } else if (dent == phba->debug_InjErrLBA) {
2282                if (phba->lpfc_injerr_lba == (sector_t)(-1))
2283                        cnt = scnprintf(cbuf, 32, "off\n");
2284                else
2285                        cnt = scnprintf(cbuf, 32, "0x%llx\n",
2286                                 (uint64_t) phba->lpfc_injerr_lba);
2287        } else
2288                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2289                         "0547 Unknown debugfs error injection entry\n");
2290
2291        return simple_read_from_buffer(buf, nbytes, ppos, &cbuf, cnt);
2292}
2293
2294static ssize_t
2295lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
2296        size_t nbytes, loff_t *ppos)
2297{
2298        struct dentry *dent = file->f_path.dentry;
2299        struct lpfc_hba *phba = file->private_data;
2300        char dstbuf[33];
2301        uint64_t tmp = 0;
2302        int size;
2303
2304        memset(dstbuf, 0, 33);
2305        size = (nbytes < 32) ? nbytes : 32;
2306        if (copy_from_user(dstbuf, buf, size))
2307                return 0;
2308
2309        if (dent == phba->debug_InjErrLBA) {
2310                if ((buf[0] == 'o') && (buf[1] == 'f') && (buf[2] == 'f'))
2311                        tmp = (uint64_t)(-1);
2312        }
2313
2314        if ((tmp == 0) && (kstrtoull(dstbuf, 0, &tmp)))
2315                return 0;
2316
2317        if (dent == phba->debug_writeGuard)
2318                phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp;
2319        else if (dent == phba->debug_writeApp)
2320                phba->lpfc_injerr_wapp_cnt = (uint32_t)tmp;
2321        else if (dent == phba->debug_writeRef)
2322                phba->lpfc_injerr_wref_cnt = (uint32_t)tmp;
2323        else if (dent == phba->debug_readGuard)
2324                phba->lpfc_injerr_rgrd_cnt = (uint32_t)tmp;
2325        else if (dent == phba->debug_readApp)
2326                phba->lpfc_injerr_rapp_cnt = (uint32_t)tmp;
2327        else if (dent == phba->debug_readRef)
2328                phba->lpfc_injerr_rref_cnt = (uint32_t)tmp;
2329        else if (dent == phba->debug_InjErrLBA)
2330                phba->lpfc_injerr_lba = (sector_t)tmp;
2331        else if (dent == phba->debug_InjErrNPortID)
2332                phba->lpfc_injerr_nportid = (uint32_t)(tmp & Mask_DID);
2333        else if (dent == phba->debug_InjErrWWPN) {
2334                tmp = cpu_to_be64(tmp);
2335                memcpy(&phba->lpfc_injerr_wwpn, &tmp, sizeof(struct lpfc_name));
2336        } else
2337                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2338                         "0548 Unknown debugfs error injection entry\n");
2339
2340        return nbytes;
2341}
2342
2343static int
2344lpfc_debugfs_dif_err_release(struct inode *inode, struct file *file)
2345{
2346        return 0;
2347}
2348
2349/**
2350 * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file
2351 * @inode: The inode pointer that contains a vport pointer.
2352 * @file: The file pointer to attach the log output.
2353 *
2354 * Description:
2355 * This routine is the entry point for the debugfs open file operation. It gets
2356 * the vport from the i_private field in @inode, allocates the necessary buffer
2357 * for the log, fills the buffer from the in-memory log for this vport, and then
2358 * returns a pointer to that log in the private_data field in @file.
2359 *
2360 * Returns:
2361 * This function returns zero if successful. On error it will return a negative
2362 * error value.
2363 **/
2364static int
2365lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file)
2366{
2367        struct lpfc_vport *vport = inode->i_private;
2368        struct lpfc_debug *debug;
2369        int rc = -ENOMEM;
2370
2371        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2372        if (!debug)
2373                goto out;
2374
2375        /* Round to page boundary */
2376        debug->buffer = kmalloc(LPFC_NODELIST_SIZE, GFP_KERNEL);
2377        if (!debug->buffer) {
2378                kfree(debug);
2379                goto out;
2380        }
2381
2382        debug->len = lpfc_debugfs_nodelist_data(vport, debug->buffer,
2383                LPFC_NODELIST_SIZE);
2384        file->private_data = debug;
2385
2386        rc = 0;
2387out:
2388        return rc;
2389}
2390
2391/**
2392 * lpfc_debugfs_lseek - Seek through a debugfs file
2393 * @file: The file pointer to seek through.
2394 * @off: The offset to seek to or the amount to seek by.
2395 * @whence: Indicates how to seek.
2396 *
2397 * Description:
2398 * This routine is the entry point for the debugfs lseek file operation. The
2399 * @whence parameter indicates whether @off is the offset to directly seek to,
2400 * or if it is a value to seek forward or reverse by. This function figures out
2401 * what the new offset of the debugfs file will be and assigns that value to the
2402 * f_pos field of @file.
2403 *
2404 * Returns:
2405 * This function returns the new offset if successful and returns a negative
2406 * error if unable to process the seek.
2407 **/
2408static loff_t
2409lpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
2410{
2411        struct lpfc_debug *debug = file->private_data;
2412        return fixed_size_llseek(file, off, whence, debug->len);
2413}
2414
2415/**
2416 * lpfc_debugfs_read - Read a debugfs file
2417 * @file: The file pointer to read from.
2418 * @buf: The buffer to copy the data to.
2419 * @nbytes: The number of bytes to read.
2420 * @ppos: The position in the file to start reading from.
2421 *
2422 * Description:
2423 * This routine reads data from from the buffer indicated in the private_data
2424 * field of @file. It will start reading at @ppos and copy up to @nbytes of
2425 * data to @buf.
2426 *
2427 * Returns:
2428 * This function returns the amount of data that was read (this could be less
2429 * than @nbytes if the end of the file was reached) or a negative error value.
2430 **/
2431static ssize_t
2432lpfc_debugfs_read(struct file *file, char __user *buf,
2433                  size_t nbytes, loff_t *ppos)
2434{
2435        struct lpfc_debug *debug = file->private_data;
2436
2437        return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer,
2438                                       debug->len);
2439}
2440
2441/**
2442 * lpfc_debugfs_release - Release the buffer used to store debugfs file data
2443 * @inode: The inode pointer that contains a vport pointer. (unused)
2444 * @file: The file pointer that contains the buffer to release.
2445 *
2446 * Description:
2447 * This routine frees the buffer that was allocated when the debugfs file was
2448 * opened.
2449 *
2450 * Returns:
2451 * This function returns zero.
2452 **/
2453static int
2454lpfc_debugfs_release(struct inode *inode, struct file *file)
2455{
2456        struct lpfc_debug *debug = file->private_data;
2457
2458        kfree(debug->buffer);
2459        kfree(debug);
2460
2461        return 0;
2462}
2463
2464static int
2465lpfc_debugfs_dumpDataDif_release(struct inode *inode, struct file *file)
2466{
2467        struct lpfc_debug *debug = file->private_data;
2468
2469        debug->buffer = NULL;
2470        kfree(debug);
2471
2472        return 0;
2473}
2474
2475/**
2476 * lpfc_debugfs_multixripools_write - Clear multi-XRI pools statistics
2477 * @file: The file pointer to read from.
2478 * @buf: The buffer to copy the user data from.
2479 * @nbytes: The number of bytes to get.
2480 * @ppos: The position in the file to start reading from.
2481 *
2482 * Description:
2483 * This routine clears multi-XRI pools statistics when buf contains "clear".
2484 *
2485 * Return Value:
2486 * It returns the @nbytges passing in from debugfs user space when successful.
2487 * In case of error conditions, it returns proper error code back to the user
2488 * space.
2489 **/
2490static ssize_t
2491lpfc_debugfs_multixripools_write(struct file *file, const char __user *buf,
2492                                 size_t nbytes, loff_t *ppos)
2493{
2494        struct lpfc_debug *debug = file->private_data;
2495        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
2496        char mybuf[64];
2497        char *pbuf;
2498        u32 i;
2499        u32 hwq_count;
2500        struct lpfc_sli4_hdw_queue *qp;
2501        struct lpfc_multixri_pool *multixri_pool;
2502
2503        if (nbytes > 64)
2504                nbytes = 64;
2505
2506        /* Protect copy from user */
2507        if (!access_ok(buf, nbytes))
2508                return -EFAULT;
2509
2510        memset(mybuf, 0, sizeof(mybuf));
2511
2512        if (copy_from_user(mybuf, buf, nbytes))
2513                return -EFAULT;
2514        pbuf = &mybuf[0];
2515
2516        if ((strncmp(pbuf, "clear", strlen("clear"))) == 0) {
2517                hwq_count = phba->cfg_hdw_queue;
2518                for (i = 0; i < hwq_count; i++) {
2519                        qp = &phba->sli4_hba.hdwq[i];
2520                        multixri_pool = qp->p_multixri_pool;
2521                        if (!multixri_pool)
2522                                continue;
2523
2524                        qp->empty_io_bufs = 0;
2525                        multixri_pool->pbl_empty_count = 0;
2526#ifdef LPFC_MXP_STAT
2527                        multixri_pool->above_limit_count = 0;
2528                        multixri_pool->below_limit_count = 0;
2529                        multixri_pool->stat_max_hwm = 0;
2530                        multixri_pool->local_pbl_hit_count = 0;
2531                        multixri_pool->other_pbl_hit_count = 0;
2532
2533                        multixri_pool->stat_pbl_count = 0;
2534                        multixri_pool->stat_pvt_count = 0;
2535                        multixri_pool->stat_busy_count = 0;
2536                        multixri_pool->stat_snapshot_taken = 0;
2537#endif
2538                }
2539                return strlen(pbuf);
2540        }
2541
2542        return -EINVAL;
2543}
2544
2545static int
2546lpfc_debugfs_nvmestat_open(struct inode *inode, struct file *file)
2547{
2548        struct lpfc_vport *vport = inode->i_private;
2549        struct lpfc_debug *debug;
2550        int rc = -ENOMEM;
2551
2552        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2553        if (!debug)
2554                goto out;
2555
2556         /* Round to page boundary */
2557        debug->buffer = kmalloc(LPFC_NVMESTAT_SIZE, GFP_KERNEL);
2558        if (!debug->buffer) {
2559                kfree(debug);
2560                goto out;
2561        }
2562
2563        debug->len = lpfc_debugfs_nvmestat_data(vport, debug->buffer,
2564                LPFC_NVMESTAT_SIZE);
2565
2566        debug->i_private = inode->i_private;
2567        file->private_data = debug;
2568
2569        rc = 0;
2570out:
2571        return rc;
2572}
2573
2574static ssize_t
2575lpfc_debugfs_nvmestat_write(struct file *file, const char __user *buf,
2576                            size_t nbytes, loff_t *ppos)
2577{
2578        struct lpfc_debug *debug = file->private_data;
2579        struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private;
2580        struct lpfc_hba   *phba = vport->phba;
2581        struct lpfc_nvmet_tgtport *tgtp;
2582        char mybuf[64];
2583        char *pbuf;
2584
2585        if (!phba->targetport)
2586                return -ENXIO;
2587
2588        if (nbytes > 64)
2589                nbytes = 64;
2590
2591        memset(mybuf, 0, sizeof(mybuf));
2592
2593        if (copy_from_user(mybuf, buf, nbytes))
2594                return -EFAULT;
2595        pbuf = &mybuf[0];
2596
2597        tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
2598        if ((strncmp(pbuf, "reset", strlen("reset")) == 0) ||
2599            (strncmp(pbuf, "zero", strlen("zero")) == 0)) {
2600                atomic_set(&tgtp->rcv_ls_req_in, 0);
2601                atomic_set(&tgtp->rcv_ls_req_out, 0);
2602                atomic_set(&tgtp->rcv_ls_req_drop, 0);
2603                atomic_set(&tgtp->xmt_ls_abort, 0);
2604                atomic_set(&tgtp->xmt_ls_abort_cmpl, 0);
2605                atomic_set(&tgtp->xmt_ls_rsp, 0);
2606                atomic_set(&tgtp->xmt_ls_drop, 0);
2607                atomic_set(&tgtp->xmt_ls_rsp_error, 0);
2608                atomic_set(&tgtp->xmt_ls_rsp_cmpl, 0);
2609
2610                atomic_set(&tgtp->rcv_fcp_cmd_in, 0);
2611                atomic_set(&tgtp->rcv_fcp_cmd_out, 0);
2612                atomic_set(&tgtp->rcv_fcp_cmd_drop, 0);
2613                atomic_set(&tgtp->xmt_fcp_drop, 0);
2614                atomic_set(&tgtp->xmt_fcp_read_rsp, 0);
2615                atomic_set(&tgtp->xmt_fcp_read, 0);
2616                atomic_set(&tgtp->xmt_fcp_write, 0);
2617                atomic_set(&tgtp->xmt_fcp_rsp, 0);
2618                atomic_set(&tgtp->xmt_fcp_release, 0);
2619                atomic_set(&tgtp->xmt_fcp_rsp_cmpl, 0);
2620                atomic_set(&tgtp->xmt_fcp_rsp_error, 0);
2621                atomic_set(&tgtp->xmt_fcp_rsp_drop, 0);
2622
2623                atomic_set(&tgtp->xmt_fcp_abort, 0);
2624                atomic_set(&tgtp->xmt_fcp_abort_cmpl, 0);
2625                atomic_set(&tgtp->xmt_abort_sol, 0);
2626                atomic_set(&tgtp->xmt_abort_unsol, 0);
2627                atomic_set(&tgtp->xmt_abort_rsp, 0);
2628                atomic_set(&tgtp->xmt_abort_rsp_error, 0);
2629        }
2630        return nbytes;
2631}
2632
2633static int
2634lpfc_debugfs_scsistat_open(struct inode *inode, struct file *file)
2635{
2636        struct lpfc_vport *vport = inode->i_private;
2637        struct lpfc_debug *debug;
2638        int rc = -ENOMEM;
2639
2640        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2641        if (!debug)
2642                goto out;
2643
2644         /* Round to page boundary */
2645        debug->buffer = kzalloc(LPFC_SCSISTAT_SIZE, GFP_KERNEL);
2646        if (!debug->buffer) {
2647                kfree(debug);
2648                goto out;
2649        }
2650
2651        debug->len = lpfc_debugfs_scsistat_data(vport, debug->buffer,
2652                LPFC_SCSISTAT_SIZE);
2653
2654        debug->i_private = inode->i_private;
2655        file->private_data = debug;
2656
2657        rc = 0;
2658out:
2659        return rc;
2660}
2661
2662static ssize_t
2663lpfc_debugfs_scsistat_write(struct file *file, const char __user *buf,
2664                            size_t nbytes, loff_t *ppos)
2665{
2666        struct lpfc_debug *debug = file->private_data;
2667        struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private;
2668        struct lpfc_hba *phba = vport->phba;
2669        char mybuf[6] = {0};
2670        int i;
2671
2672        /* Protect copy from user */
2673        if (!access_ok(buf, nbytes))
2674                return -EFAULT;
2675
2676        if (copy_from_user(mybuf, buf, (nbytes >= sizeof(mybuf)) ?
2677                                       (sizeof(mybuf) - 1) : nbytes))
2678                return -EFAULT;
2679
2680        if ((strncmp(&mybuf[0], "reset", strlen("reset")) == 0) ||
2681            (strncmp(&mybuf[0], "zero", strlen("zero")) == 0)) {
2682                for (i = 0; i < phba->cfg_hdw_queue; i++) {
2683                        memset(&phba->sli4_hba.hdwq[i].scsi_cstat, 0,
2684                               sizeof(phba->sli4_hba.hdwq[i].scsi_cstat));
2685                }
2686        }
2687
2688        return nbytes;
2689}
2690
2691static int
2692lpfc_debugfs_nvmektime_open(struct inode *inode, struct file *file)
2693{
2694        struct lpfc_vport *vport = inode->i_private;
2695        struct lpfc_debug *debug;
2696        int rc = -ENOMEM;
2697
2698        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2699        if (!debug)
2700                goto out;
2701
2702         /* Round to page boundary */
2703        debug->buffer = kmalloc(LPFC_NVMEKTIME_SIZE, GFP_KERNEL);
2704        if (!debug->buffer) {
2705                kfree(debug);
2706                goto out;
2707        }
2708
2709        debug->len = lpfc_debugfs_nvmektime_data(vport, debug->buffer,
2710                LPFC_NVMEKTIME_SIZE);
2711
2712        debug->i_private = inode->i_private;
2713        file->private_data = debug;
2714
2715        rc = 0;
2716out:
2717        return rc;
2718}
2719
2720static ssize_t
2721lpfc_debugfs_nvmektime_write(struct file *file, const char __user *buf,
2722                             size_t nbytes, loff_t *ppos)
2723{
2724        struct lpfc_debug *debug = file->private_data;
2725        struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private;
2726        struct lpfc_hba   *phba = vport->phba;
2727        char mybuf[64];
2728        char *pbuf;
2729
2730        if (nbytes > 64)
2731                nbytes = 64;
2732
2733        memset(mybuf, 0, sizeof(mybuf));
2734
2735        if (copy_from_user(mybuf, buf, nbytes))
2736                return -EFAULT;
2737        pbuf = &mybuf[0];
2738
2739        if ((strncmp(pbuf, "on", sizeof("on") - 1) == 0)) {
2740                phba->ktime_data_samples = 0;
2741                phba->ktime_status_samples = 0;
2742                phba->ktime_seg1_total = 0;
2743                phba->ktime_seg1_max = 0;
2744                phba->ktime_seg1_min = 0xffffffff;
2745                phba->ktime_seg2_total = 0;
2746                phba->ktime_seg2_max = 0;
2747                phba->ktime_seg2_min = 0xffffffff;
2748                phba->ktime_seg3_total = 0;
2749                phba->ktime_seg3_max = 0;
2750                phba->ktime_seg3_min = 0xffffffff;
2751                phba->ktime_seg4_total = 0;
2752                phba->ktime_seg4_max = 0;
2753                phba->ktime_seg4_min = 0xffffffff;
2754                phba->ktime_seg5_total = 0;
2755                phba->ktime_seg5_max = 0;
2756                phba->ktime_seg5_min = 0xffffffff;
2757                phba->ktime_seg6_total = 0;
2758                phba->ktime_seg6_max = 0;
2759                phba->ktime_seg6_min = 0xffffffff;
2760                phba->ktime_seg7_total = 0;
2761                phba->ktime_seg7_max = 0;
2762                phba->ktime_seg7_min = 0xffffffff;
2763                phba->ktime_seg8_total = 0;
2764                phba->ktime_seg8_max = 0;
2765                phba->ktime_seg8_min = 0xffffffff;
2766                phba->ktime_seg9_total = 0;
2767                phba->ktime_seg9_max = 0;
2768                phba->ktime_seg9_min = 0xffffffff;
2769                phba->ktime_seg10_total = 0;
2770                phba->ktime_seg10_max = 0;
2771                phba->ktime_seg10_min = 0xffffffff;
2772
2773                phba->ktime_on = 1;
2774                return strlen(pbuf);
2775        } else if ((strncmp(pbuf, "off",
2776                   sizeof("off") - 1) == 0)) {
2777                phba->ktime_on = 0;
2778                return strlen(pbuf);
2779        } else if ((strncmp(pbuf, "zero",
2780                   sizeof("zero") - 1) == 0)) {
2781                phba->ktime_data_samples = 0;
2782                phba->ktime_status_samples = 0;
2783                phba->ktime_seg1_total = 0;
2784                phba->ktime_seg1_max = 0;
2785                phba->ktime_seg1_min = 0xffffffff;
2786                phba->ktime_seg2_total = 0;
2787                phba->ktime_seg2_max = 0;
2788                phba->ktime_seg2_min = 0xffffffff;
2789                phba->ktime_seg3_total = 0;
2790                phba->ktime_seg3_max = 0;
2791                phba->ktime_seg3_min = 0xffffffff;
2792                phba->ktime_seg4_total = 0;
2793                phba->ktime_seg4_max = 0;
2794                phba->ktime_seg4_min = 0xffffffff;
2795                phba->ktime_seg5_total = 0;
2796                phba->ktime_seg5_max = 0;
2797                phba->ktime_seg5_min = 0xffffffff;
2798                phba->ktime_seg6_total = 0;
2799                phba->ktime_seg6_max = 0;
2800                phba->ktime_seg6_min = 0xffffffff;
2801                phba->ktime_seg7_total = 0;
2802                phba->ktime_seg7_max = 0;
2803                phba->ktime_seg7_min = 0xffffffff;
2804                phba->ktime_seg8_total = 0;
2805                phba->ktime_seg8_max = 0;
2806                phba->ktime_seg8_min = 0xffffffff;
2807                phba->ktime_seg9_total = 0;
2808                phba->ktime_seg9_max = 0;
2809                phba->ktime_seg9_min = 0xffffffff;
2810                phba->ktime_seg10_total = 0;
2811                phba->ktime_seg10_max = 0;
2812                phba->ktime_seg10_min = 0xffffffff;
2813                return strlen(pbuf);
2814        }
2815        return -EINVAL;
2816}
2817
2818static int
2819lpfc_debugfs_nvmeio_trc_open(struct inode *inode, struct file *file)
2820{
2821        struct lpfc_hba *phba = inode->i_private;
2822        struct lpfc_debug *debug;
2823        int rc = -ENOMEM;
2824
2825        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2826        if (!debug)
2827                goto out;
2828
2829         /* Round to page boundary */
2830        debug->buffer = kmalloc(LPFC_NVMEIO_TRC_SIZE, GFP_KERNEL);
2831        if (!debug->buffer) {
2832                kfree(debug);
2833                goto out;
2834        }
2835
2836        debug->len = lpfc_debugfs_nvmeio_trc_data(phba, debug->buffer,
2837                LPFC_NVMEIO_TRC_SIZE);
2838
2839        debug->i_private = inode->i_private;
2840        file->private_data = debug;
2841
2842        rc = 0;
2843out:
2844        return rc;
2845}
2846
2847static ssize_t
2848lpfc_debugfs_nvmeio_trc_write(struct file *file, const char __user *buf,
2849                              size_t nbytes, loff_t *ppos)
2850{
2851        struct lpfc_debug *debug = file->private_data;
2852        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
2853        int i;
2854        unsigned long sz;
2855        char mybuf[64];
2856        char *pbuf;
2857
2858        if (nbytes > 64)
2859                nbytes = 64;
2860
2861        memset(mybuf, 0, sizeof(mybuf));
2862
2863        if (copy_from_user(mybuf, buf, nbytes))
2864                return -EFAULT;
2865        pbuf = &mybuf[0];
2866
2867        if ((strncmp(pbuf, "off", sizeof("off") - 1) == 0)) {
2868                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2869                                "0570 nvmeio_trc_off\n");
2870                phba->nvmeio_trc_output_idx = 0;
2871                phba->nvmeio_trc_on = 0;
2872                return strlen(pbuf);
2873        } else if ((strncmp(pbuf, "on", sizeof("on") - 1) == 0)) {
2874                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2875                                "0571 nvmeio_trc_on\n");
2876                phba->nvmeio_trc_output_idx = 0;
2877                phba->nvmeio_trc_on = 1;
2878                return strlen(pbuf);
2879        }
2880
2881        /* We must be off to allocate the trace buffer */
2882        if (phba->nvmeio_trc_on != 0)
2883                return -EINVAL;
2884
2885        /* If not on or off, the parameter is the trace buffer size */
2886        i = kstrtoul(pbuf, 0, &sz);
2887        if (i)
2888                return -EINVAL;
2889        phba->nvmeio_trc_size = (uint32_t)sz;
2890
2891        /* It must be a power of 2 - round down */
2892        i = 0;
2893        while (sz > 1) {
2894                sz = sz >> 1;
2895                i++;
2896        }
2897        sz = (1 << i);
2898        if (phba->nvmeio_trc_size != sz)
2899                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2900                                "0572 nvmeio_trc_size changed to %ld\n",
2901                                sz);
2902        phba->nvmeio_trc_size = (uint32_t)sz;
2903
2904        /* If one previously exists, free it */
2905        kfree(phba->nvmeio_trc);
2906
2907        /* Allocate new trace buffer and initialize */
2908        phba->nvmeio_trc = kzalloc((sizeof(struct lpfc_debugfs_nvmeio_trc) *
2909                                    sz), GFP_KERNEL);
2910        if (!phba->nvmeio_trc) {
2911                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2912                                "0573 Cannot create debugfs "
2913                                "nvmeio_trc buffer\n");
2914                return -ENOMEM;
2915        }
2916        atomic_set(&phba->nvmeio_trc_cnt, 0);
2917        phba->nvmeio_trc_on = 0;
2918        phba->nvmeio_trc_output_idx = 0;
2919
2920        return strlen(pbuf);
2921}
2922
2923static int
2924lpfc_debugfs_cpucheck_open(struct inode *inode, struct file *file)
2925{
2926        struct lpfc_vport *vport = inode->i_private;
2927        struct lpfc_debug *debug;
2928        int rc = -ENOMEM;
2929
2930        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2931        if (!debug)
2932                goto out;
2933
2934         /* Round to page boundary */
2935        debug->buffer = kmalloc(LPFC_CPUCHECK_SIZE, GFP_KERNEL);
2936        if (!debug->buffer) {
2937                kfree(debug);
2938                goto out;
2939        }
2940
2941        debug->len = lpfc_debugfs_cpucheck_data(vport, debug->buffer,
2942                LPFC_CPUCHECK_SIZE);
2943
2944        debug->i_private = inode->i_private;
2945        file->private_data = debug;
2946
2947        rc = 0;
2948out:
2949        return rc;
2950}
2951
2952static ssize_t
2953lpfc_debugfs_cpucheck_write(struct file *file, const char __user *buf,
2954                            size_t nbytes, loff_t *ppos)
2955{
2956        struct lpfc_debug *debug = file->private_data;
2957        struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private;
2958        struct lpfc_hba   *phba = vport->phba;
2959        struct lpfc_sli4_hdw_queue *qp;
2960        char mybuf[64];
2961        char *pbuf;
2962        int i, j;
2963
2964        if (nbytes > 64)
2965                nbytes = 64;
2966
2967        memset(mybuf, 0, sizeof(mybuf));
2968
2969        if (copy_from_user(mybuf, buf, nbytes))
2970                return -EFAULT;
2971        pbuf = &mybuf[0];
2972
2973        if ((strncmp(pbuf, "on", sizeof("on") - 1) == 0)) {
2974                if (phba->nvmet_support)
2975                        phba->cpucheck_on |= LPFC_CHECK_NVMET_IO;
2976                else
2977                        phba->cpucheck_on |= (LPFC_CHECK_NVME_IO |
2978                                LPFC_CHECK_SCSI_IO);
2979                return strlen(pbuf);
2980        } else if ((strncmp(pbuf, "nvme_on", sizeof("nvme_on") - 1) == 0)) {
2981                if (phba->nvmet_support)
2982                        phba->cpucheck_on |= LPFC_CHECK_NVMET_IO;
2983                else
2984                        phba->cpucheck_on |= LPFC_CHECK_NVME_IO;
2985                return strlen(pbuf);
2986        } else if ((strncmp(pbuf, "scsi_on", sizeof("scsi_on") - 1) == 0)) {
2987                phba->cpucheck_on |= LPFC_CHECK_SCSI_IO;
2988                return strlen(pbuf);
2989        } else if ((strncmp(pbuf, "rcv",
2990                   sizeof("rcv") - 1) == 0)) {
2991                if (phba->nvmet_support)
2992                        phba->cpucheck_on |= LPFC_CHECK_NVMET_RCV;
2993                else
2994                        return -EINVAL;
2995                return strlen(pbuf);
2996        } else if ((strncmp(pbuf, "off",
2997                   sizeof("off") - 1) == 0)) {
2998                phba->cpucheck_on = LPFC_CHECK_OFF;
2999                return strlen(pbuf);
3000        } else if ((strncmp(pbuf, "zero",
3001                   sizeof("zero") - 1) == 0)) {
3002                for (i = 0; i < phba->cfg_hdw_queue; i++) {
3003                        qp = &phba->sli4_hba.hdwq[i];
3004
3005                        for (j = 0; j < LPFC_CHECK_CPU_CNT; j++) {
3006                                qp->cpucheck_rcv_io[j] = 0;
3007                                qp->cpucheck_xmt_io[j] = 0;
3008                                qp->cpucheck_cmpl_io[j] = 0;
3009                        }
3010                }
3011                return strlen(pbuf);
3012        }
3013        return -EINVAL;
3014}
3015
3016/*
3017 * ---------------------------------
3018 * iDiag debugfs file access methods
3019 * ---------------------------------
3020 *
3021 * All access methods are through the proper SLI4 PCI function's debugfs
3022 * iDiag directory:
3023 *
3024 *     /sys/kernel/debug/lpfc/fn<#>/iDiag
3025 */
3026
3027/**
3028 * lpfc_idiag_cmd_get - Get and parse idiag debugfs comands from user space
3029 * @buf: The pointer to the user space buffer.
3030 * @nbytes: The number of bytes in the user space buffer.
3031 * @idiag_cmd: pointer to the idiag command struct.
3032 *
3033 * This routine reads data from debugfs user space buffer and parses the
3034 * buffer for getting the idiag command and arguments. The while space in
3035 * between the set of data is used as the parsing separator.
3036 *
3037 * This routine returns 0 when successful, it returns proper error code
3038 * back to the user space in error conditions.
3039 */
3040static int lpfc_idiag_cmd_get(const char __user *buf, size_t nbytes,
3041                              struct lpfc_idiag_cmd *idiag_cmd)
3042{
3043        char mybuf[64];
3044        char *pbuf, *step_str;
3045        int i;
3046        size_t bsize;
3047
3048        memset(mybuf, 0, sizeof(mybuf));
3049        memset(idiag_cmd, 0, sizeof(*idiag_cmd));
3050        bsize = min(nbytes, (sizeof(mybuf)-1));
3051
3052        if (copy_from_user(mybuf, buf, bsize))
3053                return -EFAULT;
3054        pbuf = &mybuf[0];
3055        step_str = strsep(&pbuf, "\t ");
3056
3057        /* The opcode must present */
3058        if (!step_str)
3059                return -EINVAL;
3060
3061        idiag_cmd->opcode = simple_strtol(step_str, NULL, 0);
3062        if (idiag_cmd->opcode == 0)
3063                return -EINVAL;
3064
3065        for (i = 0; i < LPFC_IDIAG_CMD_DATA_SIZE; i++) {
3066                step_str = strsep(&pbuf, "\t ");
3067                if (!step_str)
3068                        return i;
3069                idiag_cmd->data[i] = simple_strtol(step_str, NULL, 0);
3070        }
3071        return i;
3072}
3073
3074/**
3075 * lpfc_idiag_open - idiag open debugfs
3076 * @inode: The inode pointer that contains a pointer to phba.
3077 * @file: The file pointer to attach the file operation.
3078 *
3079 * Description:
3080 * This routine is the entry point for the debugfs open file operation. It
3081 * gets the reference to phba from the i_private field in @inode, it then
3082 * allocates buffer for the file operation, performs the necessary PCI config
3083 * space read into the allocated buffer according to the idiag user command
3084 * setup, and then returns a pointer to buffer in the private_data field in
3085 * @file.
3086 *
3087 * Returns:
3088 * This function returns zero if successful. On error it will return an
3089 * negative error value.
3090 **/
3091static int
3092lpfc_idiag_open(struct inode *inode, struct file *file)
3093{
3094        struct lpfc_debug *debug;
3095
3096        debug = kmalloc(sizeof(*debug), GFP_KERNEL);
3097        if (!debug)
3098                return -ENOMEM;
3099
3100        debug->i_private = inode->i_private;
3101        debug->buffer = NULL;
3102        file->private_data = debug;
3103
3104        return 0;
3105}
3106
3107/**
3108 * lpfc_idiag_release - Release idiag access file operation
3109 * @inode: The inode pointer that contains a vport pointer. (unused)
3110 * @file: The file pointer that contains the buffer to release.
3111 *
3112 * Description:
3113 * This routine is the generic release routine for the idiag access file
3114 * operation, it frees the buffer that was allocated when the debugfs file
3115 * was opened.
3116 *
3117 * Returns:
3118 * This function returns zero.
3119 **/
3120static int
3121lpfc_idiag_release(struct inode *inode, struct file *file)
3122{
3123        struct lpfc_debug *debug = file->private_data;
3124
3125        /* Free the buffers to the file operation */
3126        kfree(debug->buffer);
3127        kfree(debug);
3128
3129        return 0;
3130}
3131
3132/**
3133 * lpfc_idiag_cmd_release - Release idiag cmd access file operation
3134 * @inode: The inode pointer that contains a vport pointer. (unused)
3135 * @file: The file pointer that contains the buffer to release.
3136 *
3137 * Description:
3138 * This routine frees the buffer that was allocated when the debugfs file
3139 * was opened. It also reset the fields in the idiag command struct in the
3140 * case of command for write operation.
3141 *
3142 * Returns:
3143 * This function returns zero.
3144 **/
3145static int
3146lpfc_idiag_cmd_release(struct inode *inode, struct file *file)
3147{
3148        struct lpfc_debug *debug = file->private_data;
3149
3150        if (debug->op == LPFC_IDIAG_OP_WR) {
3151                switch (idiag.cmd.opcode) {
3152                case LPFC_IDIAG_CMD_PCICFG_WR:
3153                case LPFC_IDIAG_CMD_PCICFG_ST:
3154                case LPFC_IDIAG_CMD_PCICFG_CL:
3155                case LPFC_IDIAG_CMD_QUEACC_WR:
3156                case LPFC_IDIAG_CMD_QUEACC_ST:
3157                case LPFC_IDIAG_CMD_QUEACC_CL:
3158                        memset(&idiag, 0, sizeof(idiag));
3159                        break;
3160                default:
3161                        break;
3162                }
3163        }
3164
3165        /* Free the buffers to the file operation */
3166        kfree(debug->buffer);
3167        kfree(debug);
3168
3169        return 0;
3170}
3171
3172/**
3173 * lpfc_idiag_pcicfg_read - idiag debugfs read pcicfg
3174 * @file: The file pointer to read from.
3175 * @buf: The buffer to copy the data to.
3176 * @nbytes: The number of bytes to read.
3177 * @ppos: The position in the file to start reading from.
3178 *
3179 * Description:
3180 * This routine reads data from the @phba pci config space according to the
3181 * idiag command, and copies to user @buf. Depending on the PCI config space
3182 * read command setup, it does either a single register read of a byte
3183 * (8 bits), a word (16 bits), or a dword (32 bits) or browsing through all
3184 * registers from the 4K extended PCI config space.
3185 *
3186 * Returns:
3187 * This function returns the amount of data that was read (this could be less
3188 * than @nbytes if the end of the file was reached) or a negative error value.
3189 **/
3190static ssize_t
3191lpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes,
3192                       loff_t *ppos)
3193{
3194        struct lpfc_debug *debug = file->private_data;
3195        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
3196        int offset_label, offset, len = 0, index = LPFC_PCI_CFG_RD_SIZE;
3197        int where, count;
3198        char *pbuffer;
3199        struct pci_dev *pdev;
3200        uint32_t u32val;
3201        uint16_t u16val;
3202        uint8_t u8val;
3203
3204        pdev = phba->pcidev;
3205        if (!pdev)
3206                return 0;
3207
3208        /* This is a user read operation */
3209        debug->op = LPFC_IDIAG_OP_RD;
3210
3211        if (!debug->buffer)
3212                debug->buffer = kmalloc(LPFC_PCI_CFG_SIZE, GFP_KERNEL);
3213        if (!debug->buffer)
3214                return 0;
3215        pbuffer = debug->buffer;
3216
3217        if (*ppos)
3218                return 0;
3219
3220        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) {
3221                where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
3222                count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
3223        } else
3224                return 0;
3225
3226        /* Read single PCI config space register */
3227        switch (count) {
3228        case SIZE_U8: /* byte (8 bits) */
3229                pci_read_config_byte(pdev, where, &u8val);
3230                len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
3231                                "%03x: %02x\n", where, u8val);
3232                break;
3233        case SIZE_U16: /* word (16 bits) */
3234                pci_read_config_word(pdev, where, &u16val);
3235                len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
3236                                "%03x: %04x\n", where, u16val);
3237                break;
3238        case SIZE_U32: /* double word (32 bits) */
3239                pci_read_config_dword(pdev, where, &u32val);
3240                len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
3241                                "%03x: %08x\n", where, u32val);
3242                break;
3243        case LPFC_PCI_CFG_BROWSE: /* browse all */
3244                goto pcicfg_browse;
3245                break;
3246        default:
3247                /* illegal count */
3248                len = 0;
3249                break;
3250        }
3251        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
3252
3253pcicfg_browse:
3254
3255        /* Browse all PCI config space registers */
3256        offset_label = idiag.offset.last_rd;
3257        offset = offset_label;
3258
3259        /* Read PCI config space */
3260        len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
3261                        "%03x: ", offset_label);
3262        while (index > 0) {
3263                pci_read_config_dword(pdev, offset, &u32val);
3264                len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
3265                                "%08x ", u32val);
3266                offset += sizeof(uint32_t);
3267                if (offset >= LPFC_PCI_CFG_SIZE) {
3268                        len += scnprintf(pbuffer+len,
3269                                        LPFC_PCI_CFG_SIZE-len, "\n");
3270                        break;
3271                }
3272                index -= sizeof(uint32_t);
3273                if (!index)
3274                        len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
3275                                        "\n");
3276                else if (!(index % (8 * sizeof(uint32_t)))) {
3277                        offset_label += (8 * sizeof(uint32_t));
3278                        len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
3279                                        "\n%03x: ", offset_label);
3280                }
3281        }
3282
3283        /* Set up the offset for next portion of pci cfg read */
3284        if (index == 0) {
3285                idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE;
3286                if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE)
3287                        idiag.offset.last_rd = 0;
3288        } else
3289                idiag.offset.last_rd = 0;
3290
3291        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
3292}
3293
3294/**
3295 * lpfc_idiag_pcicfg_write - Syntax check and set up idiag pcicfg commands
3296 * @file: The file pointer to read from.
3297 * @buf: The buffer to copy the user data from.
3298 * @nbytes: The number of bytes to get.
3299 * @ppos: The position in the file to start reading from.
3300 *
3301 * This routine get the debugfs idiag command struct from user space and
3302 * then perform the syntax check for PCI config space read or write command
3303 * accordingly. In the case of PCI config space read command, it sets up
3304 * the command in the idiag command struct for the debugfs read operation.
3305 * In the case of PCI config space write operation, it executes the write
3306 * operation into the PCI config space accordingly.
3307 *
3308 * It returns the @nbytges passing in from debugfs user space when successful.
3309 * In case of error conditions, it returns proper error code back to the user
3310 * space.
3311 */
3312static ssize_t
3313lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf,
3314                        size_t nbytes, loff_t *ppos)
3315{
3316        struct lpfc_debug *debug = file->private_data;
3317        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
3318        uint32_t where, value, count;
3319        uint32_t u32val;
3320        uint16_t u16val;
3321        uint8_t u8val;
3322        struct pci_dev *pdev;
3323        int rc;
3324
3325        pdev = phba->pcidev;
3326        if (!pdev)
3327                return -EFAULT;
3328
3329        /* This is a user write operation */
3330        debug->op = LPFC_IDIAG_OP_WR;
3331
3332        rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
3333        if (rc < 0)
3334                return rc;
3335
3336        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) {
3337                /* Sanity check on PCI config read command line arguments */
3338                if (rc != LPFC_PCI_CFG_RD_CMD_ARG)
3339                        goto error_out;
3340                /* Read command from PCI config space, set up command fields */
3341                where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
3342                count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
3343                if (count == LPFC_PCI_CFG_BROWSE) {
3344                        if (where % sizeof(uint32_t))
3345                                goto error_out;
3346                        /* Starting offset to browse */
3347                        idiag.offset.last_rd = where;
3348                } else if ((count != sizeof(uint8_t)) &&
3349                           (count != sizeof(uint16_t)) &&
3350                           (count != sizeof(uint32_t)))
3351                        goto error_out;
3352                if (count == sizeof(uint8_t)) {
3353                        if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t))
3354                                goto error_out;
3355                        if (where % sizeof(uint8_t))
3356                                goto error_out;
3357                }
3358                if (count == sizeof(uint16_t)) {
3359                        if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t))
3360                                goto error_out;
3361                        if (where % sizeof(uint16_t))
3362                                goto error_out;
3363                }
3364                if (count == sizeof(uint32_t)) {
3365                        if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t))
3366                                goto error_out;
3367                        if (where % sizeof(uint32_t))
3368                                goto error_out;
3369                }
3370        } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR ||
3371                   idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST ||
3372                   idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
3373                /* Sanity check on PCI config write command line arguments */
3374                if (rc != LPFC_PCI_CFG_WR_CMD_ARG)
3375                        goto error_out;
3376                /* Write command to PCI config space, read-modify-write */
3377                where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
3378                count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
3379                value = idiag.cmd.data[IDIAG_PCICFG_VALUE_INDX];
3380                /* Sanity checks */
3381                if ((count != sizeof(uint8_t)) &&
3382                    (count != sizeof(uint16_t)) &&
3383                    (count != sizeof(uint32_t)))
3384                        goto error_out;
3385                if (count == sizeof(uint8_t)) {
3386                        if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t))
3387                                goto error_out;
3388                        if (where % sizeof(uint8_t))
3389                                goto error_out;
3390                        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
3391                                pci_write_config_byte(pdev, where,
3392                                                      (uint8_t)value);
3393                        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
3394                                rc = pci_read_config_byte(pdev, where, &u8val);
3395                                if (!rc) {
3396                                        u8val |= (uint8_t)value;
3397                                        pci_write_config_byte(pdev, where,
3398                                                              u8val);
3399                                }
3400                        }
3401                        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
3402                                rc = pci_read_config_byte(pdev, where, &u8val);
3403                                if (!rc) {
3404                                        u8val &= (uint8_t)(~value);
3405                                        pci_write_config_byte(pdev, where,
3406                                                              u8val);
3407                                }
3408                        }
3409                }
3410                if (count == sizeof(uint16_t)) {
3411                        if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t))
3412                                goto error_out;
3413                        if (where % sizeof(uint16_t))
3414                                goto error_out;
3415                        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
3416                                pci_write_config_word(pdev, where,
3417                                                      (uint16_t)value);
3418                        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
3419                                rc = pci_read_config_word(pdev, where, &u16val);
3420                                if (!rc) {
3421                                        u16val |= (uint16_t)value;
3422                                        pci_write_config_word(pdev, where,
3423                                                              u16val);
3424                                }
3425                        }
3426                        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
3427                                rc = pci_read_config_word(pdev, where, &u16val);
3428                                if (!rc) {
3429                                        u16val &= (uint16_t)(~value);
3430                                        pci_write_config_word(pdev, where,
3431                                                              u16val);
3432                                }
3433                        }
3434                }
3435                if (count == sizeof(uint32_t)) {
3436                        if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t))
3437                                goto error_out;
3438                        if (where % sizeof(uint32_t))
3439                                goto error_out;
3440                        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
3441                                pci_write_config_dword(pdev, where, value);
3442                        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
3443                                rc = pci_read_config_dword(pdev, where,
3444                                                           &u32val);
3445                                if (!rc) {
3446                                        u32val |= value;
3447                                        pci_write_config_dword(pdev, where,
3448                                                               u32val);
3449                                }
3450                        }
3451                        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
3452                                rc = pci_read_config_dword(pdev, where,
3453                                                           &u32val);
3454                                if (!rc) {
3455                                        u32val &= ~value;
3456                                        pci_write_config_dword(pdev, where,
3457                                                               u32val);
3458                                }
3459                        }
3460                }
3461        } else
3462                /* All other opecodes are illegal for now */
3463                goto error_out;
3464
3465        return nbytes;
3466error_out:
3467        memset(&idiag, 0, sizeof(idiag));
3468        return -EINVAL;
3469}
3470
3471/**
3472 * lpfc_idiag_baracc_read - idiag debugfs pci bar access read
3473 * @file: The file pointer to read from.
3474 * @buf: The buffer to copy the data to.
3475 * @nbytes: The number of bytes to read.
3476 * @ppos: The position in the file to start reading from.
3477 *
3478 * Description:
3479 * This routine reads data from the @phba pci bar memory mapped space
3480 * according to the idiag command, and copies to user @buf.
3481 *
3482 * Returns:
3483 * This function returns the amount of data that was read (this could be less
3484 * than @nbytes if the end of the file was reached) or a negative error value.
3485 **/
3486static ssize_t
3487lpfc_idiag_baracc_read(struct file *file, char __user *buf, size_t nbytes,
3488                       loff_t *ppos)
3489{
3490        struct lpfc_debug *debug = file->private_data;
3491        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
3492        int offset_label, offset, offset_run, len = 0, index;
3493        int bar_num, acc_range, bar_size;
3494        char *pbuffer;
3495        void __iomem *mem_mapped_bar;
3496        uint32_t if_type;
3497        struct pci_dev *pdev;
3498        uint32_t u32val;
3499
3500        pdev = phba->pcidev;
3501        if (!pdev)
3502                return 0;
3503
3504        /* This is a user read operation */
3505        debug->op = LPFC_IDIAG_OP_RD;
3506
3507        if (!debug->buffer)
3508                debug->buffer = kmalloc(LPFC_PCI_BAR_RD_BUF_SIZE, GFP_KERNEL);
3509        if (!debug->buffer)
3510                return 0;
3511        pbuffer = debug->buffer;
3512
3513        if (*ppos)
3514                return 0;
3515
3516        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) {
3517                bar_num   = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX];
3518                offset    = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX];
3519                acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX];
3520                bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX];
3521        } else
3522                return 0;
3523
3524        if (acc_range == 0)
3525                return 0;
3526
3527        if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
3528        if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
3529                if (bar_num == IDIAG_BARACC_BAR_0)
3530                        mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
3531                else if (bar_num == IDIAG_BARACC_BAR_1)
3532                        mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p;
3533                else if (bar_num == IDIAG_BARACC_BAR_2)
3534                        mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p;
3535                else
3536                        return 0;
3537        } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
3538                if (bar_num == IDIAG_BARACC_BAR_0)
3539                        mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
3540                else
3541                        return 0;
3542        } else
3543                return 0;
3544
3545        /* Read single PCI bar space register */
3546        if (acc_range == SINGLE_WORD) {
3547                offset_run = offset;
3548                u32val = readl(mem_mapped_bar + offset_run);
3549                len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
3550                                "%05x: %08x\n", offset_run, u32val);
3551        } else
3552                goto baracc_browse;
3553
3554        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
3555
3556baracc_browse:
3557
3558        /* Browse all PCI bar space registers */
3559        offset_label = idiag.offset.last_rd;
3560        offset_run = offset_label;
3561
3562        /* Read PCI bar memory mapped space */
3563        len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
3564                        "%05x: ", offset_label);
3565        index = LPFC_PCI_BAR_RD_SIZE;
3566        while (index > 0) {
3567                u32val = readl(mem_mapped_bar + offset_run);
3568                len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
3569                                "%08x ", u32val);
3570                offset_run += sizeof(uint32_t);
3571                if (acc_range == LPFC_PCI_BAR_BROWSE) {
3572                        if (offset_run >= bar_size) {
3573                                len += scnprintf(pbuffer+len,
3574                                        LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
3575                                break;
3576                        }
3577                } else {
3578                        if (offset_run >= offset +
3579                            (acc_range * sizeof(uint32_t))) {
3580                                len += scnprintf(pbuffer+len,
3581                                        LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
3582                                break;
3583                        }
3584                }
3585                index -= sizeof(uint32_t);
3586                if (!index)
3587                        len += scnprintf(pbuffer+len,
3588                                        LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
3589                else if (!(index % (8 * sizeof(uint32_t)))) {
3590                        offset_label += (8 * sizeof(uint32_t));
3591                        len += scnprintf(pbuffer+len,
3592                                        LPFC_PCI_BAR_RD_BUF_SIZE-len,
3593                                        "\n%05x: ", offset_label);
3594                }
3595        }
3596
3597        /* Set up the offset for next portion of pci bar read */
3598        if (index == 0) {
3599                idiag.offset.last_rd += LPFC_PCI_BAR_RD_SIZE;
3600                if (acc_range == LPFC_PCI_BAR_BROWSE) {
3601                        if (idiag.offset.last_rd >= bar_size)
3602                                idiag.offset.last_rd = 0;
3603                } else {
3604                        if (offset_run >= offset +
3605                            (acc_range * sizeof(uint32_t)))
3606                                idiag.offset.last_rd = offset;
3607                }
3608        } else {
3609                if (acc_range == LPFC_PCI_BAR_BROWSE)
3610                        idiag.offset.last_rd = 0;
3611                else
3612                        idiag.offset.last_rd = offset;
3613        }
3614
3615        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
3616}
3617
3618/**
3619 * lpfc_idiag_baracc_write - Syntax check and set up idiag bar access commands
3620 * @file: The file pointer to read from.
3621 * @buf: The buffer to copy the user data from.
3622 * @nbytes: The number of bytes to get.
3623 * @ppos: The position in the file to start reading from.
3624 *
3625 * This routine get the debugfs idiag command struct from user space and
3626 * then perform the syntax check for PCI bar memory mapped space read or
3627 * write command accordingly. In the case of PCI bar memory mapped space
3628 * read command, it sets up the command in the idiag command struct for
3629 * the debugfs read operation. In the case of PCI bar memorpy mapped space
3630 * write operation, it executes the write operation into the PCI bar memory
3631 * mapped space accordingly.
3632 *
3633 * It returns the @nbytges passing in from debugfs user space when successful.
3634 * In case of error conditions, it returns proper error code back to the user
3635 * space.
3636 */
3637static ssize_t
3638lpfc_idiag_baracc_write(struct file *file, const char __user *buf,
3639                        size_t nbytes, loff_t *ppos)
3640{
3641        struct lpfc_debug *debug = file->private_data;
3642        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
3643        uint32_t bar_num, bar_size, offset, value, acc_range;
3644        struct pci_dev *pdev;
3645        void __iomem *mem_mapped_bar;
3646        uint32_t if_type;
3647        uint32_t u32val;
3648        int rc;
3649
3650        pdev = phba->pcidev;
3651        if (!pdev)
3652                return -EFAULT;
3653
3654        /* This is a user write operation */
3655        debug->op = LPFC_IDIAG_OP_WR;
3656
3657        rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
3658        if (rc < 0)
3659                return rc;
3660
3661        if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
3662        bar_num = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX];
3663
3664        if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
3665                if ((bar_num != IDIAG_BARACC_BAR_0) &&
3666                    (bar_num != IDIAG_BARACC_BAR_1) &&
3667                    (bar_num != IDIAG_BARACC_BAR_2))
3668                        goto error_out;
3669        } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
3670                if (bar_num != IDIAG_BARACC_BAR_0)
3671                        goto error_out;
3672        } else
3673                goto error_out;
3674
3675        if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
3676                if (bar_num == IDIAG_BARACC_BAR_0) {
3677                        idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
3678                                LPFC_PCI_IF0_BAR0_SIZE;
3679                        mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
3680                } else if (bar_num == IDIAG_BARACC_BAR_1) {
3681                        idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
3682                                LPFC_PCI_IF0_BAR1_SIZE;
3683                        mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p;
3684                } else if (bar_num == IDIAG_BARACC_BAR_2) {
3685                        idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
3686                                LPFC_PCI_IF0_BAR2_SIZE;
3687                        mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p;
3688                } else
3689                        goto error_out;
3690        } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
3691                if (bar_num == IDIAG_BARACC_BAR_0) {
3692                        idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
3693                                LPFC_PCI_IF2_BAR0_SIZE;
3694                        mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
3695                } else
3696                        goto error_out;
3697        } else
3698                goto error_out;
3699
3700        offset = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX];
3701        if (offset % sizeof(uint32_t))
3702                goto error_out;
3703
3704        bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX];
3705        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) {
3706                /* Sanity check on PCI config read command line arguments */
3707                if (rc != LPFC_PCI_BAR_RD_CMD_ARG)
3708                        goto error_out;
3709                acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX];
3710                if (acc_range == LPFC_PCI_BAR_BROWSE) {
3711                        if (offset > bar_size - sizeof(uint32_t))
3712                                goto error_out;
3713                        /* Starting offset to browse */
3714                        idiag.offset.last_rd = offset;
3715                } else if (acc_range > SINGLE_WORD) {
3716                        if (offset + acc_range * sizeof(uint32_t) > bar_size)
3717                                goto error_out;
3718                        /* Starting offset to browse */
3719                        idiag.offset.last_rd = offset;
3720                } else if (acc_range != SINGLE_WORD)
3721                        goto error_out;
3722        } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR ||
3723                   idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST ||
3724                   idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) {
3725                /* Sanity check on PCI bar write command line arguments */
3726                if (rc != LPFC_PCI_BAR_WR_CMD_ARG)
3727                        goto error_out;
3728                /* Write command to PCI bar space, read-modify-write */
3729                acc_range = SINGLE_WORD;
3730                value = idiag.cmd.data[IDIAG_BARACC_REG_VAL_INDX];
3731                if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR) {
3732                        writel(value, mem_mapped_bar + offset);
3733                        readl(mem_mapped_bar + offset);
3734                }
3735                if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST) {
3736                        u32val = readl(mem_mapped_bar + offset);
3737                        u32val |= value;
3738                        writel(u32val, mem_mapped_bar + offset);
3739                        readl(mem_mapped_bar + offset);
3740                }
3741                if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) {
3742                        u32val = readl(mem_mapped_bar + offset);
3743                        u32val &= ~value;
3744                        writel(u32val, mem_mapped_bar + offset);
3745                        readl(mem_mapped_bar + offset);
3746                }
3747        } else
3748                /* All other opecodes are illegal for now */
3749                goto error_out;
3750
3751        return nbytes;
3752error_out:
3753        memset(&idiag, 0, sizeof(idiag));
3754        return -EINVAL;
3755}
3756
3757static int
3758__lpfc_idiag_print_wq(struct lpfc_queue *qp, char *wqtype,
3759                        char *pbuffer, int len)
3760{
3761        if (!qp)
3762                return len;
3763
3764        len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3765                        "\t\t%s WQ info: ", wqtype);
3766        len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3767                        "AssocCQID[%04d]: WQ-STAT[oflow:x%x posted:x%llx]\n",
3768                        qp->assoc_qid, qp->q_cnt_1,
3769                        (unsigned long long)qp->q_cnt_4);
3770        len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3771                        "\t\tWQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
3772                        "HST-IDX[%04d], PRT-IDX[%04d], NTFI[%03d]",
3773                        qp->queue_id, qp->entry_count,
3774                        qp->entry_size, qp->host_index,
3775                        qp->hba_index, qp->notify_interval);
3776        len +=  scnprintf(pbuffer + len,
3777                        LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n");
3778        return len;
3779}
3780
3781static int
3782lpfc_idiag_wqs_for_cq(struct lpfc_hba *phba, char *wqtype, char *pbuffer,
3783                int *len, int max_cnt, int cq_id)
3784{
3785        struct lpfc_queue *qp;
3786        int qidx;
3787
3788        for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) {
3789                qp = phba->sli4_hba.hdwq[qidx].fcp_wq;
3790                if (qp->assoc_qid != cq_id)
3791                        continue;
3792                *len = __lpfc_idiag_print_wq(qp, wqtype, pbuffer, *len);
3793                if (*len >= max_cnt)
3794                        return 1;
3795        }
3796        if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) {
3797                for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) {
3798                        qp = phba->sli4_hba.hdwq[qidx].nvme_wq;
3799                        if (qp->assoc_qid != cq_id)
3800                                continue;
3801                        *len = __lpfc_idiag_print_wq(qp, wqtype, pbuffer, *len);
3802                        if (*len >= max_cnt)
3803                                return 1;
3804                }
3805        }
3806        return 0;
3807}
3808
3809static int
3810__lpfc_idiag_print_cq(struct lpfc_queue *qp, char *cqtype,
3811                        char *pbuffer, int len)
3812{
3813        if (!qp)
3814                return len;
3815
3816        len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3817                        "\t%s CQ info: ", cqtype);
3818        len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3819                        "AssocEQID[%02d]: CQ STAT[max:x%x relw:x%x "
3820                        "xabt:x%x wq:x%llx]\n",
3821                        qp->assoc_qid, qp->q_cnt_1, qp->q_cnt_2,
3822                        qp->q_cnt_3, (unsigned long long)qp->q_cnt_4);
3823        len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3824                        "\tCQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
3825                        "HST-IDX[%04d], NTFI[%03d], PLMT[%03d]",
3826                        qp->queue_id, qp->entry_count,
3827                        qp->entry_size, qp->host_index,
3828                        qp->notify_interval, qp->max_proc_limit);
3829
3830        len +=  scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3831                        "\n");
3832
3833        return len;
3834}
3835
3836static int
3837__lpfc_idiag_print_rqpair(struct lpfc_queue *qp, struct lpfc_queue *datqp,
3838                        char *rqtype, char *pbuffer, int len)
3839{
3840        if (!qp || !datqp)
3841                return len;
3842
3843        len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3844                        "\t\t%s RQ info: ", rqtype);
3845        len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3846                        "AssocCQID[%02d]: RQ-STAT[nopost:x%x nobuf:x%x "
3847                        "posted:x%x rcv:x%llx]\n",
3848                        qp->assoc_qid, qp->q_cnt_1, qp->q_cnt_2,
3849                        qp->q_cnt_3, (unsigned long long)qp->q_cnt_4);
3850        len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3851                        "\t\tHQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
3852                        "HST-IDX[%04d], PRT-IDX[%04d], NTFI[%03d]\n",
3853                        qp->queue_id, qp->entry_count, qp->entry_size,
3854                        qp->host_index, qp->hba_index, qp->notify_interval);
3855        len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3856                        "\t\tDQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
3857                        "HST-IDX[%04d], PRT-IDX[%04d], NTFI[%03d]\n",
3858                        datqp->queue_id, datqp->entry_count,
3859                        datqp->entry_size, datqp->host_index,
3860                        datqp->hba_index, datqp->notify_interval);
3861        return len;
3862}
3863
3864static int
3865lpfc_idiag_cqs_for_eq(struct lpfc_hba *phba, char *pbuffer,
3866                int *len, int max_cnt, int eqidx, int eq_id)
3867{
3868        struct lpfc_queue *qp;
3869        int rc;
3870
3871        qp = phba->sli4_hba.hdwq[eqidx].fcp_cq;
3872
3873        *len = __lpfc_idiag_print_cq(qp, "FCP", pbuffer, *len);
3874
3875        /* Reset max counter */
3876        qp->CQ_max_cqe = 0;
3877
3878        if (*len >= max_cnt)
3879                return 1;
3880
3881        rc = lpfc_idiag_wqs_for_cq(phba, "FCP", pbuffer, len,
3882                                   max_cnt, qp->queue_id);
3883        if (rc)
3884                return 1;
3885
3886        if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) {
3887                qp = phba->sli4_hba.hdwq[eqidx].nvme_cq;
3888
3889                *len = __lpfc_idiag_print_cq(qp, "NVME", pbuffer, *len);
3890
3891                /* Reset max counter */
3892                qp->CQ_max_cqe = 0;
3893
3894                if (*len >= max_cnt)
3895                        return 1;
3896
3897                rc = lpfc_idiag_wqs_for_cq(phba, "NVME", pbuffer, len,
3898                                           max_cnt, qp->queue_id);
3899                if (rc)
3900                        return 1;
3901        }
3902
3903        if ((eqidx < phba->cfg_nvmet_mrq) && phba->nvmet_support) {
3904                /* NVMET CQset */
3905                qp = phba->sli4_hba.nvmet_cqset[eqidx];
3906                *len = __lpfc_idiag_print_cq(qp, "NVMET CQset", pbuffer, *len);
3907
3908                /* Reset max counter */
3909                qp->CQ_max_cqe = 0;
3910
3911                if (*len >= max_cnt)
3912                        return 1;
3913
3914                /* RQ header */
3915                qp = phba->sli4_hba.nvmet_mrq_hdr[eqidx];
3916                *len = __lpfc_idiag_print_rqpair(qp,
3917                                phba->sli4_hba.nvmet_mrq_data[eqidx],
3918                                "NVMET MRQ", pbuffer, *len);
3919
3920                if (*len >= max_cnt)
3921                        return 1;
3922        }
3923
3924        return 0;
3925}
3926
3927static int
3928__lpfc_idiag_print_eq(struct lpfc_queue *qp, char *eqtype,
3929                        char *pbuffer, int len)
3930{
3931        if (!qp)
3932                return len;
3933
3934        len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3935                        "\n%s EQ info: EQ-STAT[max:x%x noE:x%x "
3936                        "cqe_proc:x%x eqe_proc:x%llx eqd %d]\n",
3937                        eqtype, qp->q_cnt_1, qp->q_cnt_2, qp->q_cnt_3,
3938                        (unsigned long long)qp->q_cnt_4, qp->q_mode);
3939        len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3940                        "EQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
3941                        "HST-IDX[%04d], NTFI[%03d], PLMT[%03d], AFFIN[%03d]",
3942                        qp->queue_id, qp->entry_count, qp->entry_size,
3943                        qp->host_index, qp->notify_interval,
3944                        qp->max_proc_limit, qp->chann);
3945        len +=  scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3946                        "\n");
3947
3948        return len;
3949}
3950
3951/**
3952 * lpfc_idiag_queinfo_read - idiag debugfs read queue information
3953 * @file: The file pointer to read from.
3954 * @buf: The buffer to copy the data to.
3955 * @nbytes: The number of bytes to read.
3956 * @ppos: The position in the file to start reading from.
3957 *
3958 * Description:
3959 * This routine reads data from the @phba SLI4 PCI function queue information,
3960 * and copies to user @buf.
3961 * This routine only returns 1 EQs worth of information. It remembers the last
3962 * EQ read and jumps to the next EQ. Thus subsequent calls to queInfo will
3963 * retrieve all EQs allocated for the phba.
3964 *
3965 * Returns:
3966 * This function returns the amount of data that was read (this could be less
3967 * than @nbytes if the end of the file was reached) or a negative error value.
3968 **/
3969static ssize_t
3970lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
3971                        loff_t *ppos)
3972{
3973        struct lpfc_debug *debug = file->private_data;
3974        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
3975        char *pbuffer;
3976        int max_cnt, rc, x, len = 0;
3977        struct lpfc_queue *qp = NULL;
3978
3979        if (!debug->buffer)
3980                debug->buffer = kmalloc(LPFC_QUE_INFO_GET_BUF_SIZE, GFP_KERNEL);
3981        if (!debug->buffer)
3982                return 0;
3983        pbuffer = debug->buffer;
3984        max_cnt = LPFC_QUE_INFO_GET_BUF_SIZE - 256;
3985
3986        if (*ppos)
3987                return 0;
3988
3989        spin_lock_irq(&phba->hbalock);
3990
3991        /* Fast-path event queue */
3992        if (phba->sli4_hba.hdwq && phba->cfg_hdw_queue) {
3993
3994                x = phba->lpfc_idiag_last_eq;
3995                phba->lpfc_idiag_last_eq++;
3996                if (phba->lpfc_idiag_last_eq >= phba->cfg_hdw_queue)
3997                        phba->lpfc_idiag_last_eq = 0;
3998
3999                len += scnprintf(pbuffer + len,
4000                                 LPFC_QUE_INFO_GET_BUF_SIZE - len,
4001                                 "HDWQ %d out of %d HBA HDWQs\n",
4002                                 x, phba->cfg_hdw_queue);
4003
4004                /* Fast-path EQ */
4005                qp = phba->sli4_hba.hdwq[x].hba_eq;
4006                if (!qp)
4007                        goto out;
4008
4009                len = __lpfc_idiag_print_eq(qp, "HBA", pbuffer, len);
4010
4011                /* Reset max counter */
4012                qp->EQ_max_eqe = 0;
4013
4014                if (len >= max_cnt)
4015                        goto too_big;
4016
4017                /* will dump both fcp and nvme cqs/wqs for the eq */
4018                rc = lpfc_idiag_cqs_for_eq(phba, pbuffer, &len,
4019                        max_cnt, x, qp->queue_id);
4020                if (rc)
4021                        goto too_big;
4022
4023                /* Only EQ 0 has slow path CQs configured */
4024                if (x)
4025                        goto out;
4026
4027                /* Slow-path mailbox CQ */
4028                qp = phba->sli4_hba.mbx_cq;
4029                len = __lpfc_idiag_print_cq(qp, "MBX", pbuffer, len);
4030                if (len >= max_cnt)
4031                        goto too_big;
4032
4033                /* Slow-path MBOX MQ */
4034                qp = phba->sli4_hba.mbx_wq;
4035                len = __lpfc_idiag_print_wq(qp, "MBX", pbuffer, len);
4036                if (len >= max_cnt)
4037                        goto too_big;
4038
4039                /* Slow-path ELS response CQ */
4040                qp = phba->sli4_hba.els_cq;
4041                len = __lpfc_idiag_print_cq(qp, "ELS", pbuffer, len);
4042                /* Reset max counter */
4043                if (qp)
4044                        qp->CQ_max_cqe = 0;
4045                if (len >= max_cnt)
4046                        goto too_big;
4047
4048                /* Slow-path ELS WQ */
4049                qp = phba->sli4_hba.els_wq;
4050                len = __lpfc_idiag_print_wq(qp, "ELS", pbuffer, len);
4051                if (len >= max_cnt)
4052                        goto too_big;
4053
4054                qp = phba->sli4_hba.hdr_rq;
4055                len = __lpfc_idiag_print_rqpair(qp, phba->sli4_hba.dat_rq,
4056                                                "ELS RQpair", pbuffer, len);
4057                if (len >= max_cnt)
4058                        goto too_big;
4059
4060                /* Slow-path NVME LS response CQ */
4061                qp = phba->sli4_hba.nvmels_cq;
4062                len = __lpfc_idiag_print_cq(qp, "NVME LS",
4063                                                pbuffer, len);
4064                /* Reset max counter */
4065                if (qp)
4066                        qp->CQ_max_cqe = 0;
4067                if (len >= max_cnt)
4068                        goto too_big;
4069
4070                /* Slow-path NVME LS WQ */
4071                qp = phba->sli4_hba.nvmels_wq;
4072                len = __lpfc_idiag_print_wq(qp, "NVME LS",
4073                                                pbuffer, len);
4074                if (len >= max_cnt)
4075                        goto too_big;
4076
4077                goto out;
4078        }
4079
4080        spin_unlock_irq(&phba->hbalock);
4081        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
4082
4083too_big:
4084        len +=  scnprintf(pbuffer + len,
4085                LPFC_QUE_INFO_GET_BUF_SIZE - len, "Truncated ...\n");
4086out:
4087        spin_unlock_irq(&phba->hbalock);
4088        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
4089}
4090
4091/**
4092 * lpfc_idiag_que_param_check - queue access command parameter sanity check
4093 * @q: The pointer to queue structure.
4094 * @index: The index into a queue entry.
4095 * @count: The number of queue entries to access.
4096 *
4097 * Description:
4098 * The routine performs sanity check on device queue access method commands.
4099 *
4100 * Returns:
4101 * This function returns -EINVAL when fails the sanity check, otherwise, it
4102 * returns 0.
4103 **/
4104static int
4105lpfc_idiag_que_param_check(struct lpfc_queue *q, int index, int count)
4106{
4107        /* Only support single entry read or browsing */
4108        if ((count != 1) && (count != LPFC_QUE_ACC_BROWSE))
4109                return -EINVAL;
4110        if (index > q->entry_count - 1)
4111                return -EINVAL;
4112        return 0;
4113}
4114
4115/**
4116 * lpfc_idiag_queacc_read_qe - read a single entry from the given queue index
4117 * @pbuffer: The pointer to buffer to copy the read data into.
4118 * @pque: The pointer to the queue to be read.
4119 * @index: The index into the queue entry.
4120 *
4121 * Description:
4122 * This routine reads out a single entry from the given queue's index location
4123 * and copies it into the buffer provided.
4124 *
4125 * Returns:
4126 * This function returns 0 when it fails, otherwise, it returns the length of
4127 * the data read into the buffer provided.
4128 **/
4129static int
4130lpfc_idiag_queacc_read_qe(char *pbuffer, int len, struct lpfc_queue *pque,
4131                          uint32_t index)
4132{
4133        int offset, esize;
4134        uint32_t *pentry;
4135
4136        if (!pbuffer || !pque)
4137                return 0;
4138
4139        esize = pque->entry_size;
4140        len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len,
4141                        "QE-INDEX[%04d]:\n", index);
4142
4143        offset = 0;
4144        pentry = lpfc_sli4_qe(pque, index);
4145        while (esize > 0) {
4146                len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len,
4147                                "%08x ", *pentry);
4148                pentry++;
4149                offset += sizeof(uint32_t);
4150                esize -= sizeof(uint32_t);
4151                if (esize > 0 && !(offset % (4 * sizeof(uint32_t))))
4152                        len += scnprintf(pbuffer+len,
4153                                        LPFC_QUE_ACC_BUF_SIZE-len, "\n");
4154        }
4155        len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, "\n");
4156
4157        return len;
4158}
4159
4160/**
4161 * lpfc_idiag_queacc_read - idiag debugfs read port queue
4162 * @file: The file pointer to read from.
4163 * @buf: The buffer to copy the data to.
4164 * @nbytes: The number of bytes to read.
4165 * @ppos: The position in the file to start reading from.
4166 *
4167 * Description:
4168 * This routine reads data from the @phba device queue memory according to the
4169 * idiag command, and copies to user @buf. Depending on the queue dump read
4170 * command setup, it does either a single queue entry read or browing through
4171 * all entries of the queue.
4172 *
4173 * Returns:
4174 * This function returns the amount of data that was read (this could be less
4175 * than @nbytes if the end of the file was reached) or a negative error value.
4176 **/
4177static ssize_t
4178lpfc_idiag_queacc_read(struct file *file, char __user *buf, size_t nbytes,
4179                       loff_t *ppos)
4180{
4181        struct lpfc_debug *debug = file->private_data;
4182        uint32_t last_index, index, count;
4183        struct lpfc_queue *pque = NULL;
4184        char *pbuffer;
4185        int len = 0;
4186
4187        /* This is a user read operation */
4188        debug->op = LPFC_IDIAG_OP_RD;
4189
4190        if (!debug->buffer)
4191                debug->buffer = kmalloc(LPFC_QUE_ACC_BUF_SIZE, GFP_KERNEL);
4192        if (!debug->buffer)
4193                return 0;
4194        pbuffer = debug->buffer;
4195
4196        if (*ppos)
4197                return 0;
4198
4199        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
4200                index = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX];
4201                count = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX];
4202                pque = (struct lpfc_queue *)idiag.ptr_private;
4203        } else
4204                return 0;
4205
4206        /* Browse the queue starting from index */
4207        if (count == LPFC_QUE_ACC_BROWSE)
4208                goto que_browse;
4209
4210        /* Read a single entry from the queue */
4211        len = lpfc_idiag_queacc_read_qe(pbuffer, len, pque, index);
4212
4213        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
4214
4215que_browse:
4216
4217        /* Browse all entries from the queue */
4218        last_index = idiag.offset.last_rd;
4219        index = last_index;
4220
4221        while (len < LPFC_QUE_ACC_SIZE - pque->entry_size) {
4222                len = lpfc_idiag_queacc_read_qe(pbuffer, len, pque, index);
4223                index++;
4224                if (index > pque->entry_count - 1)
4225                        break;
4226        }
4227
4228        /* Set up the offset for next portion of pci cfg read */
4229        if (index > pque->entry_count - 1)
4230                index = 0;
4231        idiag.offset.last_rd = index;
4232
4233        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
4234}
4235
4236/**
4237 * lpfc_idiag_queacc_write - Syntax check and set up idiag queacc commands
4238 * @file: The file pointer to read from.
4239 * @buf: The buffer to copy the user data from.
4240 * @nbytes: The number of bytes to get.
4241 * @ppos: The position in the file to start reading from.
4242 *
4243 * This routine get the debugfs idiag command struct from user space and then
4244 * perform the syntax check for port queue read (dump) or write (set) command
4245 * accordingly. In the case of port queue read command, it sets up the command
4246 * in the idiag command struct for the following debugfs read operation. In
4247 * the case of port queue write operation, it executes the write operation
4248 * into the port queue entry accordingly.
4249 *
4250 * It returns the @nbytges passing in from debugfs user space when successful.
4251 * In case of error conditions, it returns proper error code back to the user
4252 * space.
4253 **/
4254static ssize_t
4255lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
4256                        size_t nbytes, loff_t *ppos)
4257{
4258        struct lpfc_debug *debug = file->private_data;
4259        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
4260        uint32_t qidx, quetp, queid, index, count, offset, value;
4261        uint32_t *pentry;
4262        struct lpfc_queue *pque, *qp;
4263        int rc;
4264
4265        /* This is a user write operation */
4266        debug->op = LPFC_IDIAG_OP_WR;
4267
4268        rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
4269        if (rc < 0)
4270                return rc;
4271
4272        /* Get and sanity check on command feilds */
4273        quetp  = idiag.cmd.data[IDIAG_QUEACC_QUETP_INDX];
4274        queid  = idiag.cmd.data[IDIAG_QUEACC_QUEID_INDX];
4275        index  = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX];
4276        count  = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX];
4277        offset = idiag.cmd.data[IDIAG_QUEACC_OFFST_INDX];
4278        value  = idiag.cmd.data[IDIAG_QUEACC_VALUE_INDX];
4279
4280        /* Sanity check on command line arguments */
4281        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR ||
4282            idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST ||
4283            idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL) {
4284                if (rc != LPFC_QUE_ACC_WR_CMD_ARG)
4285                        goto error_out;
4286                if (count != 1)
4287                        goto error_out;
4288        } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
4289                if (rc != LPFC_QUE_ACC_RD_CMD_ARG)
4290                        goto error_out;
4291        } else
4292                goto error_out;
4293
4294        switch (quetp) {
4295        case LPFC_IDIAG_EQ:
4296                /* HBA event queue */
4297                if (phba->sli4_hba.hdwq) {
4298                        for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) {
4299                                qp = phba->sli4_hba.hdwq[qidx].hba_eq;
4300                                if (qp && qp->queue_id == queid) {
4301                                        /* Sanity check */
4302                                        rc = lpfc_idiag_que_param_check(qp,
4303                                                index, count);
4304                                        if (rc)
4305                                                goto error_out;
4306                                        idiag.ptr_private = qp;
4307                                        goto pass_check;
4308                                }
4309                        }
4310                }
4311                goto error_out;
4312                break;
4313        case LPFC_IDIAG_CQ:
4314                /* MBX complete queue */
4315                if (phba->sli4_hba.mbx_cq &&
4316                    phba->sli4_hba.mbx_cq->queue_id == queid) {
4317                        /* Sanity check */
4318                        rc = lpfc_idiag_que_param_check(
4319                                        phba->sli4_hba.mbx_cq, index, count);
4320                        if (rc)
4321                                goto error_out;
4322                        idiag.ptr_private = phba->sli4_hba.mbx_cq;
4323                        goto pass_check;
4324                }
4325                /* ELS complete queue */
4326                if (phba->sli4_hba.els_cq &&
4327                    phba->sli4_hba.els_cq->queue_id == queid) {
4328                        /* Sanity check */
4329                        rc = lpfc_idiag_que_param_check(
4330                                        phba->sli4_hba.els_cq, index, count);
4331                        if (rc)
4332                                goto error_out;
4333                        idiag.ptr_private = phba->sli4_hba.els_cq;
4334                        goto pass_check;
4335                }
4336                /* NVME LS complete queue */
4337                if (phba->sli4_hba.nvmels_cq &&
4338                    phba->sli4_hba.nvmels_cq->queue_id == queid) {
4339                        /* Sanity check */
4340                        rc = lpfc_idiag_que_param_check(
4341                                        phba->sli4_hba.nvmels_cq, index, count);
4342                        if (rc)
4343                                goto error_out;
4344                        idiag.ptr_private = phba->sli4_hba.nvmels_cq;
4345                        goto pass_check;
4346                }
4347                /* FCP complete queue */
4348                if (phba->sli4_hba.hdwq) {
4349                        for (qidx = 0; qidx < phba->cfg_hdw_queue;
4350                                                                qidx++) {
4351                                qp = phba->sli4_hba.hdwq[qidx].fcp_cq;
4352                                if (qp && qp->queue_id == queid) {
4353                                        /* Sanity check */
4354                                        rc = lpfc_idiag_que_param_check(
4355                                                qp, index, count);
4356                                        if (rc)
4357                                                goto error_out;
4358                                        idiag.ptr_private = qp;
4359                                        goto pass_check;
4360                                }
4361                        }
4362                }
4363                /* NVME complete queue */
4364                if (phba->sli4_hba.hdwq) {
4365                        qidx = 0;
4366                        do {
4367                                qp = phba->sli4_hba.hdwq[qidx].nvme_cq;
4368                                if (qp && qp->queue_id == queid) {
4369                                        /* Sanity check */
4370                                        rc = lpfc_idiag_que_param_check(
4371                                                qp, index, count);
4372                                        if (rc)
4373                                                goto error_out;
4374                                        idiag.ptr_private = qp;
4375                                        goto pass_check;
4376                                }
4377                        } while (++qidx < phba->cfg_hdw_queue);
4378                }
4379                goto error_out;
4380                break;
4381        case LPFC_IDIAG_MQ:
4382                /* MBX work queue */
4383                if (phba->sli4_hba.mbx_wq &&
4384                    phba->sli4_hba.mbx_wq->queue_id == queid) {
4385                        /* Sanity check */
4386                        rc = lpfc_idiag_que_param_check(
4387                                        phba->sli4_hba.mbx_wq, index, count);
4388                        if (rc)
4389                                goto error_out;
4390                        idiag.ptr_private = phba->sli4_hba.mbx_wq;
4391                        goto pass_check;
4392                }
4393                goto error_out;
4394                break;
4395        case LPFC_IDIAG_WQ:
4396                /* ELS work queue */
4397                if (phba->sli4_hba.els_wq &&
4398                    phba->sli4_hba.els_wq->queue_id == queid) {
4399                        /* Sanity check */
4400                        rc = lpfc_idiag_que_param_check(
4401                                        phba->sli4_hba.els_wq, index, count);
4402                        if (rc)
4403                                goto error_out;
4404                        idiag.ptr_private = phba->sli4_hba.els_wq;
4405                        goto pass_check;
4406                }
4407                /* NVME LS work queue */
4408                if (phba->sli4_hba.nvmels_wq &&
4409                    phba->sli4_hba.nvmels_wq->queue_id == queid) {
4410                        /* Sanity check */
4411                        rc = lpfc_idiag_que_param_check(
4412                                        phba->sli4_hba.nvmels_wq, index, count);
4413                        if (rc)
4414                                goto error_out;
4415                        idiag.ptr_private = phba->sli4_hba.nvmels_wq;
4416                        goto pass_check;
4417                }
4418
4419                if (phba->sli4_hba.hdwq) {
4420                        /* FCP/SCSI work queue */
4421                        for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) {
4422                                qp = phba->sli4_hba.hdwq[qidx].fcp_wq;
4423                                if (qp && qp->queue_id == queid) {
4424                                        /* Sanity check */
4425                                        rc = lpfc_idiag_que_param_check(
4426                                                qp, index, count);
4427                                        if (rc)
4428                                                goto error_out;
4429                                        idiag.ptr_private = qp;
4430                                        goto pass_check;
4431                                }
4432                        }
4433                        /* NVME work queue */
4434                        for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) {
4435                                qp = phba->sli4_hba.hdwq[qidx].nvme_wq;
4436                                if (qp && qp->queue_id == queid) {
4437                                        /* Sanity check */
4438                                        rc = lpfc_idiag_que_param_check(
4439                                                qp, index, count);
4440                                        if (rc)
4441                                                goto error_out;
4442                                        idiag.ptr_private = qp;
4443                                        goto pass_check;
4444                                }
4445                        }
4446                }
4447
4448                goto error_out;
4449                break;
4450        case LPFC_IDIAG_RQ:
4451                /* HDR queue */
4452                if (phba->sli4_hba.hdr_rq &&
4453                    phba->sli4_hba.hdr_rq->queue_id == queid) {
4454                        /* Sanity check */
4455                        rc = lpfc_idiag_que_param_check(
4456                                        phba->sli4_hba.hdr_rq, index, count);
4457                        if (rc)
4458                                goto error_out;
4459                        idiag.ptr_private = phba->sli4_hba.hdr_rq;
4460                        goto pass_check;
4461                }
4462                /* DAT queue */
4463                if (phba->sli4_hba.dat_rq &&
4464                    phba->sli4_hba.dat_rq->queue_id == queid) {
4465                        /* Sanity check */
4466                        rc = lpfc_idiag_que_param_check(
4467                                        phba->sli4_hba.dat_rq, index, count);
4468                        if (rc)
4469                                goto error_out;
4470                        idiag.ptr_private = phba->sli4_hba.dat_rq;
4471                        goto pass_check;
4472                }
4473                goto error_out;
4474                break;
4475        default:
4476                goto error_out;
4477                break;
4478        }
4479
4480pass_check:
4481
4482        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
4483                if (count == LPFC_QUE_ACC_BROWSE)
4484                        idiag.offset.last_rd = index;
4485        }
4486
4487        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR ||
4488            idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST ||
4489            idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL) {
4490                /* Additional sanity checks on write operation */
4491                pque = (struct lpfc_queue *)idiag.ptr_private;
4492                if (offset > pque->entry_size/sizeof(uint32_t) - 1)
4493                        goto error_out;
4494                pentry = lpfc_sli4_qe(pque, index);
4495                pentry += offset;
4496                if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR)
4497                        *pentry = value;
4498                if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST)
4499                        *pentry |= value;
4500                if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL)
4501                        *pentry &= ~value;
4502        }
4503        return nbytes;
4504
4505error_out:
4506        /* Clean out command structure on command error out */
4507        memset(&idiag, 0, sizeof(idiag));
4508        return -EINVAL;
4509}
4510
4511/**
4512 * lpfc_idiag_drbacc_read_reg - idiag debugfs read a doorbell register
4513 * @phba: The pointer to hba structure.
4514 * @pbuffer: The pointer to the buffer to copy the data to.
4515 * @len: The length of bytes to copied.
4516 * @drbregid: The id to doorbell registers.
4517 *
4518 * Description:
4519 * This routine reads a doorbell register and copies its content to the
4520 * user buffer pointed to by @pbuffer.
4521 *
4522 * Returns:
4523 * This function returns the amount of data that was copied into @pbuffer.
4524 **/
4525static int
4526lpfc_idiag_drbacc_read_reg(struct lpfc_hba *phba, char *pbuffer,
4527                           int len, uint32_t drbregid)
4528{
4529
4530        if (!pbuffer)
4531                return 0;
4532
4533        switch (drbregid) {
4534        case LPFC_DRB_EQ:
4535                len += scnprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE-len,
4536                                "EQ-DRB-REG: 0x%08x\n",
4537                                readl(phba->sli4_hba.EQDBregaddr));
4538                break;
4539        case LPFC_DRB_CQ:
4540                len += scnprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE - len,
4541                                "CQ-DRB-REG: 0x%08x\n",
4542                                readl(phba->sli4_hba.CQDBregaddr));
4543                break;
4544        case LPFC_DRB_MQ:
4545                len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
4546                                "MQ-DRB-REG:   0x%08x\n",
4547                                readl(phba->sli4_hba.MQDBregaddr));
4548                break;
4549        case LPFC_DRB_WQ:
4550                len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
4551                                "WQ-DRB-REG:   0x%08x\n",
4552                                readl(phba->sli4_hba.WQDBregaddr));
4553                break;
4554        case LPFC_DRB_RQ:
4555                len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
4556                                "RQ-DRB-REG:   0x%08x\n",
4557                                readl(phba->sli4_hba.RQDBregaddr));
4558                break;
4559        default:
4560                break;
4561        }
4562
4563        return len;
4564}
4565
4566/**
4567 * lpfc_idiag_drbacc_read - idiag debugfs read port doorbell
4568 * @file: The file pointer to read from.
4569 * @buf: The buffer to copy the data to.
4570 * @nbytes: The number of bytes to read.
4571 * @ppos: The position in the file to start reading from.
4572 *
4573 * Description:
4574 * This routine reads data from the @phba device doorbell register according
4575 * to the idiag command, and copies to user @buf. Depending on the doorbell
4576 * register read command setup, it does either a single doorbell register
4577 * read or dump all doorbell registers.
4578 *
4579 * Returns:
4580 * This function returns the amount of data that was read (this could be less
4581 * than @nbytes if the end of the file was reached) or a negative error value.
4582 **/
4583static ssize_t
4584lpfc_idiag_drbacc_read(struct file *file, char __user *buf, size_t nbytes,
4585                       loff_t *ppos)
4586{
4587        struct lpfc_debug *debug = file->private_data;
4588        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
4589        uint32_t drb_reg_id, i;
4590        char *pbuffer;
4591        int len = 0;
4592
4593        /* This is a user read operation */
4594        debug->op = LPFC_IDIAG_OP_RD;
4595
4596        if (!debug->buffer)
4597                debug->buffer = kmalloc(LPFC_DRB_ACC_BUF_SIZE, GFP_KERNEL);
4598        if (!debug->buffer)
4599                return 0;
4600        pbuffer = debug->buffer;
4601
4602        if (*ppos)
4603                return 0;
4604
4605        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD)
4606                drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX];
4607        else
4608                return 0;
4609
4610        if (drb_reg_id == LPFC_DRB_ACC_ALL)
4611                for (i = 1; i <= LPFC_DRB_MAX; i++)
4612                        len = lpfc_idiag_drbacc_read_reg(phba,
4613                                                         pbuffer, len, i);
4614        else
4615                len = lpfc_idiag_drbacc_read_reg(phba,
4616                                                 pbuffer, len, drb_reg_id);
4617
4618        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
4619}
4620
4621/**
4622 * lpfc_idiag_drbacc_write - Syntax check and set up idiag drbacc commands
4623 * @file: The file pointer to read from.
4624 * @buf: The buffer to copy the user data from.
4625 * @nbytes: The number of bytes to get.
4626 * @ppos: The position in the file to start reading from.
4627 *
4628 * This routine get the debugfs idiag command struct from user space and then
4629 * perform the syntax check for port doorbell register read (dump) or write
4630 * (set) command accordingly. In the case of port queue read command, it sets
4631 * up the command in the idiag command struct for the following debugfs read
4632 * operation. In the case of port doorbell register write operation, it
4633 * executes the write operation into the port doorbell register accordingly.
4634 *
4635 * It returns the @nbytges passing in from debugfs user space when successful.
4636 * In case of error conditions, it returns proper error code back to the user
4637 * space.
4638 **/
4639static ssize_t
4640lpfc_idiag_drbacc_write(struct file *file, const char __user *buf,
4641                        size_t nbytes, loff_t *ppos)
4642{
4643        struct lpfc_debug *debug = file->private_data;
4644        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
4645        uint32_t drb_reg_id, value, reg_val = 0;
4646        void __iomem *drb_reg;
4647        int rc;
4648
4649        /* This is a user write operation */
4650        debug->op = LPFC_IDIAG_OP_WR;
4651
4652        rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
4653        if (rc < 0)
4654                return rc;
4655
4656        /* Sanity check on command line arguments */
4657        drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX];
4658        value = idiag.cmd.data[IDIAG_DRBACC_VALUE_INDX];
4659
4660        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR ||
4661            idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST ||
4662            idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) {
4663                if (rc != LPFC_DRB_ACC_WR_CMD_ARG)
4664                        goto error_out;
4665                if (drb_reg_id > LPFC_DRB_MAX)
4666                        goto error_out;
4667        } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD) {
4668                if (rc != LPFC_DRB_ACC_RD_CMD_ARG)
4669                        goto error_out;
4670                if ((drb_reg_id > LPFC_DRB_MAX) &&
4671                    (drb_reg_id != LPFC_DRB_ACC_ALL))
4672                        goto error_out;
4673        } else
4674                goto error_out;
4675
4676        /* Perform the write access operation */
4677        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR ||
4678            idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST ||
4679            idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) {
4680                switch (drb_reg_id) {
4681                case LPFC_DRB_EQ:
4682                        drb_reg = phba->sli4_hba.EQDBregaddr;
4683                        break;
4684                case LPFC_DRB_CQ:
4685                        drb_reg = phba->sli4_hba.CQDBregaddr;
4686                        break;
4687                case LPFC_DRB_MQ:
4688                        drb_reg = phba->sli4_hba.MQDBregaddr;
4689                        break;
4690                case LPFC_DRB_WQ:
4691                        drb_reg = phba->sli4_hba.WQDBregaddr;
4692                        break;
4693                case LPFC_DRB_RQ:
4694                        drb_reg = phba->sli4_hba.RQDBregaddr;
4695                        break;
4696                default:
4697                        goto error_out;
4698                }
4699
4700                if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR)
4701                        reg_val = value;
4702                if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST) {
4703                        reg_val = readl(drb_reg);
4704                        reg_val |= value;
4705                }
4706                if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) {
4707                        reg_val = readl(drb_reg);
4708                        reg_val &= ~value;
4709                }
4710                writel(reg_val, drb_reg);
4711                readl(drb_reg); /* flush */
4712        }
4713        return nbytes;
4714
4715error_out:
4716        /* Clean out command structure on command error out */
4717        memset(&idiag, 0, sizeof(idiag));
4718        return -EINVAL;
4719}
4720
4721/**
4722 * lpfc_idiag_ctlacc_read_reg - idiag debugfs read a control registers
4723 * @phba: The pointer to hba structure.
4724 * @pbuffer: The pointer to the buffer to copy the data to.
4725 * @len: The length of bytes to copied.
4726 * @drbregid: The id to doorbell registers.
4727 *
4728 * Description:
4729 * This routine reads a control register and copies its content to the
4730 * user buffer pointed to by @pbuffer.
4731 *
4732 * Returns:
4733 * This function returns the amount of data that was copied into @pbuffer.
4734 **/
4735static int
4736lpfc_idiag_ctlacc_read_reg(struct lpfc_hba *phba, char *pbuffer,
4737                           int len, uint32_t ctlregid)
4738{
4739
4740        if (!pbuffer)
4741                return 0;
4742
4743        switch (ctlregid) {
4744        case LPFC_CTL_PORT_SEM:
4745                len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
4746                                "Port SemReg:   0x%08x\n",
4747                                readl(phba->sli4_hba.conf_regs_memmap_p +
4748                                      LPFC_CTL_PORT_SEM_OFFSET));
4749                break;
4750        case LPFC_CTL_PORT_STA:
4751                len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
4752                                "Port StaReg:   0x%08x\n",
4753                                readl(phba->sli4_hba.conf_regs_memmap_p +
4754                                      LPFC_CTL_PORT_STA_OFFSET));
4755                break;
4756        case LPFC_CTL_PORT_CTL:
4757                len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
4758                                "Port CtlReg:   0x%08x\n",
4759                                readl(phba->sli4_hba.conf_regs_memmap_p +
4760                                      LPFC_CTL_PORT_CTL_OFFSET));
4761                break;
4762        case LPFC_CTL_PORT_ER1:
4763                len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
4764                                "Port Er1Reg:   0x%08x\n",
4765                                readl(phba->sli4_hba.conf_regs_memmap_p +
4766                                      LPFC_CTL_PORT_ER1_OFFSET));
4767                break;
4768        case LPFC_CTL_PORT_ER2:
4769                len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
4770                                "Port Er2Reg:   0x%08x\n",
4771                                readl(phba->sli4_hba.conf_regs_memmap_p +
4772                                      LPFC_CTL_PORT_ER2_OFFSET));
4773                break;
4774        case LPFC_CTL_PDEV_CTL:
4775                len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
4776                                "PDev CtlReg:   0x%08x\n",
4777                                readl(phba->sli4_hba.conf_regs_memmap_p +
4778                                      LPFC_CTL_PDEV_CTL_OFFSET));
4779                break;
4780        default:
4781                break;
4782        }
4783        return len;
4784}
4785
4786/**
4787 * lpfc_idiag_ctlacc_read - idiag debugfs read port and device control register
4788 * @file: The file pointer to read from.
4789 * @buf: The buffer to copy the data to.
4790 * @nbytes: The number of bytes to read.
4791 * @ppos: The position in the file to start reading from.
4792 *
4793 * Description:
4794 * This routine reads data from the @phba port and device registers according
4795 * to the idiag command, and copies to user @buf.
4796 *
4797 * Returns:
4798 * This function returns the amount of data that was read (this could be less
4799 * than @nbytes if the end of the file was reached) or a negative error value.
4800 **/
4801static ssize_t
4802lpfc_idiag_ctlacc_read(struct file *file, char __user *buf, size_t nbytes,
4803                       loff_t *ppos)
4804{
4805        struct lpfc_debug *debug = file->private_data;
4806        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
4807        uint32_t ctl_reg_id, i;
4808        char *pbuffer;
4809        int len = 0;
4810
4811        /* This is a user read operation */
4812        debug->op = LPFC_IDIAG_OP_RD;
4813
4814        if (!debug->buffer)
4815                debug->buffer = kmalloc(LPFC_CTL_ACC_BUF_SIZE, GFP_KERNEL);
4816        if (!debug->buffer)
4817                return 0;
4818        pbuffer = debug->buffer;
4819
4820        if (*ppos)
4821                return 0;
4822
4823        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD)
4824                ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX];
4825        else
4826                return 0;
4827
4828        if (ctl_reg_id == LPFC_CTL_ACC_ALL)
4829                for (i = 1; i <= LPFC_CTL_MAX; i++)
4830                        len = lpfc_idiag_ctlacc_read_reg(phba,
4831                                                         pbuffer, len, i);
4832        else
4833                len = lpfc_idiag_ctlacc_read_reg(phba,
4834                                                 pbuffer, len, ctl_reg_id);
4835
4836        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
4837}
4838
4839/**
4840 * lpfc_idiag_ctlacc_write - Syntax check and set up idiag ctlacc commands
4841 * @file: The file pointer to read from.
4842 * @buf: The buffer to copy the user data from.
4843 * @nbytes: The number of bytes to get.
4844 * @ppos: The position in the file to start reading from.
4845 *
4846 * This routine get the debugfs idiag command struct from user space and then
4847 * perform the syntax check for port and device control register read (dump)
4848 * or write (set) command accordingly.
4849 *
4850 * It returns the @nbytges passing in from debugfs user space when successful.
4851 * In case of error conditions, it returns proper error code back to the user
4852 * space.
4853 **/
4854static ssize_t
4855lpfc_idiag_ctlacc_write(struct file *file, const char __user *buf,
4856                        size_t nbytes, loff_t *ppos)
4857{
4858        struct lpfc_debug *debug = file->private_data;
4859        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
4860        uint32_t ctl_reg_id, value, reg_val = 0;
4861        void __iomem *ctl_reg;
4862        int rc;
4863
4864        /* This is a user write operation */
4865        debug->op = LPFC_IDIAG_OP_WR;
4866
4867        rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
4868        if (rc < 0)
4869                return rc;
4870
4871        /* Sanity check on command line arguments */
4872        ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX];
4873        value = idiag.cmd.data[IDIAG_CTLACC_VALUE_INDX];
4874
4875        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR ||
4876            idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST ||
4877            idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
4878                if (rc != LPFC_CTL_ACC_WR_CMD_ARG)
4879                        goto error_out;
4880                if (ctl_reg_id > LPFC_CTL_MAX)
4881                        goto error_out;
4882        } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD) {
4883                if (rc != LPFC_CTL_ACC_RD_CMD_ARG)
4884                        goto error_out;
4885                if ((ctl_reg_id > LPFC_CTL_MAX) &&
4886                    (ctl_reg_id != LPFC_CTL_ACC_ALL))
4887                        goto error_out;
4888        } else
4889                goto error_out;
4890
4891        /* Perform the write access operation */
4892        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR ||
4893            idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST ||
4894            idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
4895                switch (ctl_reg_id) {
4896                case LPFC_CTL_PORT_SEM:
4897                        ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
4898                                        LPFC_CTL_PORT_SEM_OFFSET;
4899                        break;
4900                case LPFC_CTL_PORT_STA:
4901                        ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
4902                                        LPFC_CTL_PORT_STA_OFFSET;
4903                        break;
4904                case LPFC_CTL_PORT_CTL:
4905                        ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
4906                                        LPFC_CTL_PORT_CTL_OFFSET;
4907                        break;
4908                case LPFC_CTL_PORT_ER1:
4909                        ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
4910                                        LPFC_CTL_PORT_ER1_OFFSET;
4911                        break;
4912                case LPFC_CTL_PORT_ER2:
4913                        ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
4914                                        LPFC_CTL_PORT_ER2_OFFSET;
4915                        break;
4916                case LPFC_CTL_PDEV_CTL:
4917                        ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
4918                                        LPFC_CTL_PDEV_CTL_OFFSET;
4919                        break;
4920                default:
4921                        goto error_out;
4922                }
4923
4924                if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR)
4925                        reg_val = value;
4926                if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST) {
4927                        reg_val = readl(ctl_reg);
4928                        reg_val |= value;
4929                }
4930                if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
4931                        reg_val = readl(ctl_reg);
4932                        reg_val &= ~value;
4933                }
4934                writel(reg_val, ctl_reg);
4935                readl(ctl_reg); /* flush */
4936        }
4937        return nbytes;
4938
4939error_out:
4940        /* Clean out command structure on command error out */
4941        memset(&idiag, 0, sizeof(idiag));
4942        return -EINVAL;
4943}
4944
4945/**
4946 * lpfc_idiag_mbxacc_get_setup - idiag debugfs get mailbox access setup
4947 * @phba: Pointer to HBA context object.
4948 * @pbuffer: Pointer to data buffer.
4949 *
4950 * Description:
4951 * This routine gets the driver mailbox access debugfs setup information.
4952 *
4953 * Returns:
4954 * This function returns the amount of data that was read (this could be less
4955 * than @nbytes if the end of the file was reached) or a negative error value.
4956 **/
4957static int
4958lpfc_idiag_mbxacc_get_setup(struct lpfc_hba *phba, char *pbuffer)
4959{
4960        uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd;
4961        int len = 0;
4962
4963        mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
4964        mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
4965        mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
4966        mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
4967
4968        len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
4969                        "mbx_dump_map: 0x%08x\n", mbx_dump_map);
4970        len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
4971                        "mbx_dump_cnt: %04d\n", mbx_dump_cnt);
4972        len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
4973                        "mbx_word_cnt: %04d\n", mbx_word_cnt);
4974        len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
4975                        "mbx_mbox_cmd: 0x%02x\n", mbx_mbox_cmd);
4976
4977        return len;
4978}
4979
4980/**
4981 * lpfc_idiag_mbxacc_read - idiag debugfs read on mailbox access
4982 * @file: The file pointer to read from.
4983 * @buf: The buffer to copy the data to.
4984 * @nbytes: The number of bytes to read.
4985 * @ppos: The position in the file to start reading from.
4986 *
4987 * Description:
4988 * This routine reads data from the @phba driver mailbox access debugfs setup
4989 * information.
4990 *
4991 * Returns:
4992 * This function returns the amount of data that was read (this could be less
4993 * than @nbytes if the end of the file was reached) or a negative error value.
4994 **/
4995static ssize_t
4996lpfc_idiag_mbxacc_read(struct file *file, char __user *buf, size_t nbytes,
4997                       loff_t *ppos)
4998{
4999        struct lpfc_debug *debug = file->private_data;
5000        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
5001        char *pbuffer;
5002        int len = 0;
5003
5004        /* This is a user read operation */
5005        debug->op = LPFC_IDIAG_OP_RD;
5006
5007        if (!debug->buffer)
5008                debug->buffer = kmalloc(LPFC_MBX_ACC_BUF_SIZE, GFP_KERNEL);
5009        if (!debug->buffer)
5010                return 0;
5011        pbuffer = debug->buffer;
5012
5013        if (*ppos)
5014                return 0;
5015
5016        if ((idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP) &&
5017            (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP))
5018                return 0;
5019
5020        len = lpfc_idiag_mbxacc_get_setup(phba, pbuffer);
5021
5022        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
5023}
5024
5025/**
5026 * lpfc_idiag_mbxacc_write - Syntax check and set up idiag mbxacc commands
5027 * @file: The file pointer to read from.
5028 * @buf: The buffer to copy the user data from.
5029 * @nbytes: The number of bytes to get.
5030 * @ppos: The position in the file to start reading from.
5031 *
5032 * This routine get the debugfs idiag command struct from user space and then
5033 * perform the syntax check for driver mailbox command (dump) and sets up the
5034 * necessary states in the idiag command struct accordingly.
5035 *
5036 * It returns the @nbytges passing in from debugfs user space when successful.
5037 * In case of error conditions, it returns proper error code back to the user
5038 * space.
5039 **/
5040static ssize_t
5041lpfc_idiag_mbxacc_write(struct file *file, const char __user *buf,
5042                        size_t nbytes, loff_t *ppos)
5043{
5044        struct lpfc_debug *debug = file->private_data;
5045        uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd;
5046        int rc;
5047
5048        /* This is a user write operation */
5049        debug->op = LPFC_IDIAG_OP_WR;
5050
5051        rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
5052        if (rc < 0)
5053                return rc;
5054
5055        /* Sanity check on command line arguments */
5056        mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
5057        mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
5058        mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
5059        mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
5060
5061        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_MBXACC_DP) {
5062                if (!(mbx_dump_map & LPFC_MBX_DMP_MBX_ALL))
5063                        goto error_out;
5064                if ((mbx_dump_map & ~LPFC_MBX_DMP_MBX_ALL) &&
5065                    (mbx_dump_map != LPFC_MBX_DMP_ALL))
5066                        goto error_out;
5067                if (mbx_word_cnt > sizeof(MAILBOX_t))
5068                        goto error_out;
5069        } else if (idiag.cmd.opcode == LPFC_IDIAG_BSG_MBXACC_DP) {
5070                if (!(mbx_dump_map & LPFC_BSG_DMP_MBX_ALL))
5071                        goto error_out;
5072                if ((mbx_dump_map & ~LPFC_BSG_DMP_MBX_ALL) &&
5073                    (mbx_dump_map != LPFC_MBX_DMP_ALL))
5074                        goto error_out;
5075                if (mbx_word_cnt > (BSG_MBOX_SIZE)/4)
5076                        goto error_out;
5077                if (mbx_mbox_cmd != 0x9b)
5078                        goto error_out;
5079        } else
5080                goto error_out;
5081
5082        if (mbx_word_cnt == 0)
5083                goto error_out;
5084        if (rc != LPFC_MBX_DMP_ARG)
5085                goto error_out;
5086        if (mbx_mbox_cmd & ~0xff)
5087                goto error_out;
5088
5089        /* condition for stop mailbox dump */
5090        if (mbx_dump_cnt == 0)
5091                goto reset_out;
5092
5093        return nbytes;
5094
5095reset_out:
5096        /* Clean out command structure on command error out */
5097        memset(&idiag, 0, sizeof(idiag));
5098        return nbytes;
5099
5100error_out:
5101        /* Clean out command structure on command error out */
5102        memset(&idiag, 0, sizeof(idiag));
5103        return -EINVAL;
5104}
5105
5106/**
5107 * lpfc_idiag_extacc_avail_get - get the available extents information
5108 * @phba: pointer to lpfc hba data structure.
5109 * @pbuffer: pointer to internal buffer.
5110 * @len: length into the internal buffer data has been copied.
5111 *
5112 * Description:
5113 * This routine is to get the available extent information.
5114 *
5115 * Returns:
5116 * overall lenth of the data read into the internal buffer.
5117 **/
5118static int
5119lpfc_idiag_extacc_avail_get(struct lpfc_hba *phba, char *pbuffer, int len)
5120{
5121        uint16_t ext_cnt, ext_size;
5122
5123        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5124                        "\nAvailable Extents Information:\n");
5125
5126        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5127                        "\tPort Available VPI extents: ");
5128        lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VPI,
5129                                       &ext_cnt, &ext_size);
5130        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5131                        "Count %3d, Size %3d\n", ext_cnt, ext_size);
5132
5133        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5134                        "\tPort Available VFI extents: ");
5135        lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VFI,
5136                                       &ext_cnt, &ext_size);
5137        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5138                        "Count %3d, Size %3d\n", ext_cnt, ext_size);
5139
5140        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5141                        "\tPort Available RPI extents: ");
5142        lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_RPI,
5143                                       &ext_cnt, &ext_size);
5144        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5145                        "Count %3d, Size %3d\n", ext_cnt, ext_size);
5146
5147        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5148                        "\tPort Available XRI extents: ");
5149        lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_XRI,
5150                                       &ext_cnt, &ext_size);
5151        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5152                        "Count %3d, Size %3d\n", ext_cnt, ext_size);
5153
5154        return len;
5155}
5156
5157/**
5158 * lpfc_idiag_extacc_alloc_get - get the allocated extents information
5159 * @phba: pointer to lpfc hba data structure.
5160 * @pbuffer: pointer to internal buffer.
5161 * @len: length into the internal buffer data has been copied.
5162 *
5163 * Description:
5164 * This routine is to get the allocated extent information.
5165 *
5166 * Returns:
5167 * overall lenth of the data read into the internal buffer.
5168 **/
5169static int
5170lpfc_idiag_extacc_alloc_get(struct lpfc_hba *phba, char *pbuffer, int len)
5171{
5172        uint16_t ext_cnt, ext_size;
5173        int rc;
5174
5175        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5176                        "\nAllocated Extents Information:\n");
5177
5178        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5179                        "\tHost Allocated VPI extents: ");
5180        rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VPI,
5181                                            &ext_cnt, &ext_size);
5182        if (!rc)
5183                len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5184                                "Port %d Extent %3d, Size %3d\n",
5185                                phba->brd_no, ext_cnt, ext_size);
5186        else
5187                len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5188                                "N/A\n");
5189
5190        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5191                        "\tHost Allocated VFI extents: ");
5192        rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VFI,
5193                                            &ext_cnt, &ext_size);
5194        if (!rc)
5195                len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5196                                "Port %d Extent %3d, Size %3d\n",
5197                                phba->brd_no, ext_cnt, ext_size);
5198        else
5199                len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5200                                "N/A\n");
5201
5202        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5203                        "\tHost Allocated RPI extents: ");
5204        rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_RPI,
5205                                            &ext_cnt, &ext_size);
5206        if (!rc)
5207                len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5208                                "Port %d Extent %3d, Size %3d\n",
5209                                phba->brd_no, ext_cnt, ext_size);
5210        else
5211                len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5212                                "N/A\n");
5213
5214        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5215                        "\tHost Allocated XRI extents: ");
5216        rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_XRI,
5217                                            &ext_cnt, &ext_size);
5218        if (!rc)
5219                len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5220                                "Port %d Extent %3d, Size %3d\n",
5221                                phba->brd_no, ext_cnt, ext_size);
5222        else
5223                len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5224                                "N/A\n");
5225
5226        return len;
5227}
5228
5229/**
5230 * lpfc_idiag_extacc_drivr_get - get driver extent information
5231 * @phba: pointer to lpfc hba data structure.
5232 * @pbuffer: pointer to internal buffer.
5233 * @len: length into the internal buffer data has been copied.
5234 *
5235 * Description:
5236 * This routine is to get the driver extent information.
5237 *
5238 * Returns:
5239 * overall lenth of the data read into the internal buffer.
5240 **/
5241static int
5242lpfc_idiag_extacc_drivr_get(struct lpfc_hba *phba, char *pbuffer, int len)
5243{
5244        struct lpfc_rsrc_blks *rsrc_blks;
5245        int index;
5246
5247        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5248                        "\nDriver Extents Information:\n");
5249
5250        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5251                        "\tVPI extents:\n");
5252        index = 0;
5253        list_for_each_entry(rsrc_blks, &phba->lpfc_vpi_blk_list, list) {
5254                len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5255                                "\t\tBlock %3d: Start %4d, Count %4d\n",
5256                                index, rsrc_blks->rsrc_start,
5257                                rsrc_blks->rsrc_size);
5258                index++;
5259        }
5260        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5261                        "\tVFI extents:\n");
5262        index = 0;
5263        list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_vfi_blk_list,
5264                            list) {
5265                len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5266                                "\t\tBlock %3d: Start %4d, Count %4d\n",
5267                                index, rsrc_blks->rsrc_start,
5268                                rsrc_blks->rsrc_size);
5269                index++;
5270        }
5271
5272        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5273                        "\tRPI extents:\n");
5274        index = 0;
5275        list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_rpi_blk_list,
5276                            list) {
5277                len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5278                                "\t\tBlock %3d: Start %4d, Count %4d\n",
5279                                index, rsrc_blks->rsrc_start,
5280                                rsrc_blks->rsrc_size);
5281                index++;
5282        }
5283
5284        len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5285                        "\tXRI extents:\n");
5286        index = 0;
5287        list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_xri_blk_list,
5288                            list) {
5289                len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
5290                                "\t\tBlock %3d: Start %4d, Count %4d\n",
5291                                index, rsrc_blks->rsrc_start,
5292                                rsrc_blks->rsrc_size);
5293                index++;
5294        }
5295
5296        return len;
5297}
5298
5299/**
5300 * lpfc_idiag_extacc_write - Syntax check and set up idiag extacc commands
5301 * @file: The file pointer to read from.
5302 * @buf: The buffer to copy the user data from.
5303 * @nbytes: The number of bytes to get.
5304 * @ppos: The position in the file to start reading from.
5305 *
5306 * This routine get the debugfs idiag command struct from user space and then
5307 * perform the syntax check for extent information access commands and sets
5308 * up the necessary states in the idiag command struct accordingly.
5309 *
5310 * It returns the @nbytges passing in from debugfs user space when successful.
5311 * In case of error conditions, it returns proper error code back to the user
5312 * space.
5313 **/
5314static ssize_t
5315lpfc_idiag_extacc_write(struct file *file, const char __user *buf,
5316                        size_t nbytes, loff_t *ppos)
5317{
5318        struct lpfc_debug *debug = file->private_data;
5319        uint32_t ext_map;
5320        int rc;
5321
5322        /* This is a user write operation */
5323        debug->op = LPFC_IDIAG_OP_WR;
5324
5325        rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
5326        if (rc < 0)
5327                return rc;
5328
5329        ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX];
5330
5331        if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD)
5332                goto error_out;
5333        if (rc != LPFC_EXT_ACC_CMD_ARG)
5334                goto error_out;
5335        if (!(ext_map & LPFC_EXT_ACC_ALL))
5336                goto error_out;
5337
5338        return nbytes;
5339error_out:
5340        /* Clean out command structure on command error out */
5341        memset(&idiag, 0, sizeof(idiag));
5342        return -EINVAL;
5343}
5344
5345/**
5346 * lpfc_idiag_extacc_read - idiag debugfs read access to extent information
5347 * @file: The file pointer to read from.
5348 * @buf: The buffer to copy the data to.
5349 * @nbytes: The number of bytes to read.
5350 * @ppos: The position in the file to start reading from.
5351 *
5352 * Description:
5353 * This routine reads data from the proper extent information according to
5354 * the idiag command, and copies to user @buf.
5355 *
5356 * Returns:
5357 * This function returns the amount of data that was read (this could be less
5358 * than @nbytes if the end of the file was reached) or a negative error value.
5359 **/
5360static ssize_t
5361lpfc_idiag_extacc_read(struct file *file, char __user *buf, size_t nbytes,
5362                       loff_t *ppos)
5363{
5364        struct lpfc_debug *debug = file->private_data;
5365        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
5366        char *pbuffer;
5367        uint32_t ext_map;
5368        int len = 0;
5369
5370        /* This is a user read operation */
5371        debug->op = LPFC_IDIAG_OP_RD;
5372
5373        if (!debug->buffer)
5374                debug->buffer = kmalloc(LPFC_EXT_ACC_BUF_SIZE, GFP_KERNEL);
5375        if (!debug->buffer)
5376                return 0;
5377        pbuffer = debug->buffer;
5378        if (*ppos)
5379                return 0;
5380        if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD)
5381                return 0;
5382
5383        ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX];
5384        if (ext_map & LPFC_EXT_ACC_AVAIL)
5385                len = lpfc_idiag_extacc_avail_get(phba, pbuffer, len);
5386        if (ext_map & LPFC_EXT_ACC_ALLOC)
5387                len = lpfc_idiag_extacc_alloc_get(phba, pbuffer, len);
5388        if (ext_map & LPFC_EXT_ACC_DRIVR)
5389                len = lpfc_idiag_extacc_drivr_get(phba, pbuffer, len);
5390
5391        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
5392}
5393
5394#undef lpfc_debugfs_op_disc_trc
5395static const struct file_operations lpfc_debugfs_op_disc_trc = {
5396        .owner =        THIS_MODULE,
5397        .open =         lpfc_debugfs_disc_trc_open,
5398        .llseek =       lpfc_debugfs_lseek,
5399        .read =         lpfc_debugfs_read,
5400        .release =      lpfc_debugfs_release,
5401};
5402
5403#undef lpfc_debugfs_op_nodelist
5404static const struct file_operations lpfc_debugfs_op_nodelist = {
5405        .owner =        THIS_MODULE,
5406        .open =         lpfc_debugfs_nodelist_open,
5407        .llseek =       lpfc_debugfs_lseek,
5408        .read =         lpfc_debugfs_read,
5409        .release =      lpfc_debugfs_release,
5410};
5411
5412#undef lpfc_debugfs_op_multixripools
5413static const struct file_operations lpfc_debugfs_op_multixripools = {
5414        .owner =        THIS_MODULE,
5415        .open =         lpfc_debugfs_multixripools_open,
5416        .llseek =       lpfc_debugfs_lseek,
5417        .read =         lpfc_debugfs_read,
5418        .write =        lpfc_debugfs_multixripools_write,
5419        .release =      lpfc_debugfs_release,
5420};
5421
5422#undef lpfc_debugfs_op_hbqinfo
5423static const struct file_operations lpfc_debugfs_op_hbqinfo = {
5424        .owner =        THIS_MODULE,
5425        .open =         lpfc_debugfs_hbqinfo_open,
5426        .llseek =       lpfc_debugfs_lseek,
5427        .read =         lpfc_debugfs_read,
5428        .release =      lpfc_debugfs_release,
5429};
5430
5431#ifdef LPFC_HDWQ_LOCK_STAT
5432#undef lpfc_debugfs_op_lockstat
5433static const struct file_operations lpfc_debugfs_op_lockstat = {
5434        .owner =        THIS_MODULE,
5435        .open =         lpfc_debugfs_lockstat_open,
5436        .llseek =       lpfc_debugfs_lseek,
5437        .read =         lpfc_debugfs_read,
5438        .write =        lpfc_debugfs_lockstat_write,
5439        .release =      lpfc_debugfs_release,
5440};
5441#endif
5442
5443#undef lpfc_debugfs_op_dumpHBASlim
5444static const struct file_operations lpfc_debugfs_op_dumpHBASlim = {
5445        .owner =        THIS_MODULE,
5446        .open =         lpfc_debugfs_dumpHBASlim_open,
5447        .llseek =       lpfc_debugfs_lseek,
5448        .read =         lpfc_debugfs_read,
5449        .release =      lpfc_debugfs_release,
5450};
5451
5452#undef lpfc_debugfs_op_dumpHostSlim
5453static const struct file_operations lpfc_debugfs_op_dumpHostSlim = {
5454        .owner =        THIS_MODULE,
5455        .open =         lpfc_debugfs_dumpHostSlim_open,
5456        .llseek =       lpfc_debugfs_lseek,
5457        .read =         lpfc_debugfs_read,
5458        .release =      lpfc_debugfs_release,
5459};
5460
5461#undef lpfc_debugfs_op_nvmestat
5462static const struct file_operations lpfc_debugfs_op_nvmestat = {
5463        .owner =        THIS_MODULE,
5464        .open =         lpfc_debugfs_nvmestat_open,
5465        .llseek =       lpfc_debugfs_lseek,
5466        .read =         lpfc_debugfs_read,
5467        .write =        lpfc_debugfs_nvmestat_write,
5468        .release =      lpfc_debugfs_release,
5469};
5470
5471#undef lpfc_debugfs_op_scsistat
5472static const struct file_operations lpfc_debugfs_op_scsistat = {
5473        .owner =        THIS_MODULE,
5474        .open =         lpfc_debugfs_scsistat_open,
5475        .llseek =       lpfc_debugfs_lseek,
5476        .read =         lpfc_debugfs_read,
5477        .write =        lpfc_debugfs_scsistat_write,
5478        .release =      lpfc_debugfs_release,
5479};
5480
5481#undef lpfc_debugfs_op_nvmektime
5482static const struct file_operations lpfc_debugfs_op_nvmektime = {
5483        .owner =        THIS_MODULE,
5484        .open =         lpfc_debugfs_nvmektime_open,
5485        .llseek =       lpfc_debugfs_lseek,
5486        .read =         lpfc_debugfs_read,
5487        .write =        lpfc_debugfs_nvmektime_write,
5488        .release =      lpfc_debugfs_release,
5489};
5490
5491#undef lpfc_debugfs_op_nvmeio_trc
5492static const struct file_operations lpfc_debugfs_op_nvmeio_trc = {
5493        .owner =        THIS_MODULE,
5494        .open =         lpfc_debugfs_nvmeio_trc_open,
5495        .llseek =       lpfc_debugfs_lseek,
5496        .read =         lpfc_debugfs_read,
5497        .write =        lpfc_debugfs_nvmeio_trc_write,
5498        .release =      lpfc_debugfs_release,
5499};
5500
5501#undef lpfc_debugfs_op_cpucheck
5502static const struct file_operations lpfc_debugfs_op_cpucheck = {
5503        .owner =        THIS_MODULE,
5504        .open =         lpfc_debugfs_cpucheck_open,
5505        .llseek =       lpfc_debugfs_lseek,
5506        .read =         lpfc_debugfs_read,
5507        .write =        lpfc_debugfs_cpucheck_write,
5508        .release =      lpfc_debugfs_release,
5509};
5510
5511#undef lpfc_debugfs_op_dumpData
5512static const struct file_operations lpfc_debugfs_op_dumpData = {
5513        .owner =        THIS_MODULE,
5514        .open =         lpfc_debugfs_dumpData_open,
5515        .llseek =       lpfc_debugfs_lseek,
5516        .read =         lpfc_debugfs_read,
5517        .write =        lpfc_debugfs_dumpDataDif_write,
5518        .release =      lpfc_debugfs_dumpDataDif_release,
5519};
5520
5521#undef lpfc_debugfs_op_dumpDif
5522static const struct file_operations lpfc_debugfs_op_dumpDif = {
5523        .owner =        THIS_MODULE,
5524        .open =         lpfc_debugfs_dumpDif_open,
5525        .llseek =       lpfc_debugfs_lseek,
5526        .read =         lpfc_debugfs_read,
5527        .write =        lpfc_debugfs_dumpDataDif_write,
5528        .release =      lpfc_debugfs_dumpDataDif_release,
5529};
5530
5531#undef lpfc_debugfs_op_dif_err
5532static const struct file_operations lpfc_debugfs_op_dif_err = {
5533        .owner =        THIS_MODULE,
5534        .open =         simple_open,
5535        .llseek =       lpfc_debugfs_lseek,
5536        .read =         lpfc_debugfs_dif_err_read,
5537        .write =        lpfc_debugfs_dif_err_write,
5538        .release =      lpfc_debugfs_dif_err_release,
5539};
5540
5541#undef lpfc_debugfs_op_slow_ring_trc
5542static const struct file_operations lpfc_debugfs_op_slow_ring_trc = {
5543        .owner =        THIS_MODULE,
5544        .open =         lpfc_debugfs_slow_ring_trc_open,
5545        .llseek =       lpfc_debugfs_lseek,
5546        .read =         lpfc_debugfs_read,
5547        .release =      lpfc_debugfs_release,
5548};
5549
5550static struct dentry *lpfc_debugfs_root = NULL;
5551static atomic_t lpfc_debugfs_hba_count;
5552
5553/*
5554 * File operations for the iDiag debugfs
5555 */
5556#undef lpfc_idiag_op_pciCfg
5557static const struct file_operations lpfc_idiag_op_pciCfg = {
5558        .owner =        THIS_MODULE,
5559        .open =         lpfc_idiag_open,
5560        .llseek =       lpfc_debugfs_lseek,
5561        .read =         lpfc_idiag_pcicfg_read,
5562        .write =        lpfc_idiag_pcicfg_write,
5563        .release =      lpfc_idiag_cmd_release,
5564};
5565
5566#undef lpfc_idiag_op_barAcc
5567static const struct file_operations lpfc_idiag_op_barAcc = {
5568        .owner =        THIS_MODULE,
5569        .open =         lpfc_idiag_open,
5570        .llseek =       lpfc_debugfs_lseek,
5571        .read =         lpfc_idiag_baracc_read,
5572        .write =        lpfc_idiag_baracc_write,
5573        .release =      lpfc_idiag_cmd_release,
5574};
5575
5576#undef lpfc_idiag_op_queInfo
5577static const struct file_operations lpfc_idiag_op_queInfo = {
5578        .owner =        THIS_MODULE,
5579        .open =         lpfc_idiag_open,
5580        .read =         lpfc_idiag_queinfo_read,
5581        .release =      lpfc_idiag_release,
5582};
5583
5584#undef lpfc_idiag_op_queAcc
5585static const struct file_operations lpfc_idiag_op_queAcc = {
5586        .owner =        THIS_MODULE,
5587        .open =         lpfc_idiag_open,
5588        .llseek =       lpfc_debugfs_lseek,
5589        .read =         lpfc_idiag_queacc_read,
5590        .write =        lpfc_idiag_queacc_write,
5591        .release =      lpfc_idiag_cmd_release,
5592};
5593
5594#undef lpfc_idiag_op_drbAcc
5595static const struct file_operations lpfc_idiag_op_drbAcc = {
5596        .owner =        THIS_MODULE,
5597        .open =         lpfc_idiag_open,
5598        .llseek =       lpfc_debugfs_lseek,
5599        .read =         lpfc_idiag_drbacc_read,
5600        .write =        lpfc_idiag_drbacc_write,
5601        .release =      lpfc_idiag_cmd_release,
5602};
5603
5604#undef lpfc_idiag_op_ctlAcc
5605static const struct file_operations lpfc_idiag_op_ctlAcc = {
5606        .owner =        THIS_MODULE,
5607        .open =         lpfc_idiag_open,
5608        .llseek =       lpfc_debugfs_lseek,
5609        .read =         lpfc_idiag_ctlacc_read,
5610        .write =        lpfc_idiag_ctlacc_write,
5611        .release =      lpfc_idiag_cmd_release,
5612};
5613
5614#undef lpfc_idiag_op_mbxAcc
5615static const struct file_operations lpfc_idiag_op_mbxAcc = {
5616        .owner =        THIS_MODULE,
5617        .open =         lpfc_idiag_open,
5618        .llseek =       lpfc_debugfs_lseek,
5619        .read =         lpfc_idiag_mbxacc_read,
5620        .write =        lpfc_idiag_mbxacc_write,
5621        .release =      lpfc_idiag_cmd_release,
5622};
5623
5624#undef lpfc_idiag_op_extAcc
5625static const struct file_operations lpfc_idiag_op_extAcc = {
5626        .owner =        THIS_MODULE,
5627        .open =         lpfc_idiag_open,
5628        .llseek =       lpfc_debugfs_lseek,
5629        .read =         lpfc_idiag_extacc_read,
5630        .write =        lpfc_idiag_extacc_write,
5631        .release =      lpfc_idiag_cmd_release,
5632};
5633
5634#endif
5635
5636/* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command
5637 * @phba: Pointer to HBA context object.
5638 * @dmabuf: Pointer to a DMA buffer descriptor.
5639 *
5640 * Description:
5641 * This routine dump a bsg pass-through non-embedded mailbox command with
5642 * external buffer.
5643 **/
5644void
5645lpfc_idiag_mbxacc_dump_bsg_mbox(struct lpfc_hba *phba, enum nemb_type nemb_tp,
5646                                enum mbox_type mbox_tp, enum dma_type dma_tp,
5647                                enum sta_type sta_tp,
5648                                struct lpfc_dmabuf *dmabuf, uint32_t ext_buf)
5649{
5650#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
5651        uint32_t *mbx_mbox_cmd, *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt;
5652        char line_buf[LPFC_MBX_ACC_LBUF_SZ];
5653        int len = 0;
5654        uint32_t do_dump = 0;
5655        uint32_t *pword;
5656        uint32_t i;
5657
5658        if (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP)
5659                return;
5660
5661        mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
5662        mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
5663        mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
5664        mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
5665
5666        if (!(*mbx_dump_map & LPFC_MBX_DMP_ALL) ||
5667            (*mbx_dump_cnt == 0) ||
5668            (*mbx_word_cnt == 0))
5669                return;
5670
5671        if (*mbx_mbox_cmd != 0x9B)
5672                return;
5673
5674        if ((mbox_tp == mbox_rd) && (dma_tp == dma_mbox)) {
5675                if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_MBX) {
5676                        do_dump |= LPFC_BSG_DMP_MBX_RD_MBX;
5677                        pr_err("\nRead mbox command (x%x), "
5678                               "nemb:0x%x, extbuf_cnt:%d:\n",
5679                               sta_tp, nemb_tp, ext_buf);
5680                }
5681        }
5682        if ((mbox_tp == mbox_rd) && (dma_tp == dma_ebuf)) {
5683                if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_BUF) {
5684                        do_dump |= LPFC_BSG_DMP_MBX_RD_BUF;
5685                        pr_err("\nRead mbox buffer (x%x), "
5686                               "nemb:0x%x, extbuf_seq:%d:\n",
5687                               sta_tp, nemb_tp, ext_buf);
5688                }
5689        }
5690        if ((mbox_tp == mbox_wr) && (dma_tp == dma_mbox)) {
5691                if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_MBX) {
5692                        do_dump |= LPFC_BSG_DMP_MBX_WR_MBX;
5693                        pr_err("\nWrite mbox command (x%x), "
5694                               "nemb:0x%x, extbuf_cnt:%d:\n",
5695                               sta_tp, nemb_tp, ext_buf);
5696                }
5697        }
5698        if ((mbox_tp == mbox_wr) && (dma_tp == dma_ebuf)) {
5699                if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_BUF) {
5700                        do_dump |= LPFC_BSG_DMP_MBX_WR_BUF;
5701                        pr_err("\nWrite mbox buffer (x%x), "
5702                               "nemb:0x%x, extbuf_seq:%d:\n",
5703                               sta_tp, nemb_tp, ext_buf);
5704                }
5705        }
5706
5707        /* dump buffer content */
5708        if (do_dump) {
5709                pword = (uint32_t *)dmabuf->virt;
5710                for (i = 0; i < *mbx_word_cnt; i++) {
5711                        if (!(i % 8)) {
5712                                if (i != 0)
5713                                        pr_err("%s\n", line_buf);
5714                                len = 0;
5715                                len += scnprintf(line_buf+len,
5716                                                LPFC_MBX_ACC_LBUF_SZ-len,
5717                                                "%03d: ", i);
5718                        }
5719                        len += scnprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len,
5720                                        "%08x ", (uint32_t)*pword);
5721                        pword++;
5722                }
5723                if ((i - 1) % 8)
5724                        pr_err("%s\n", line_buf);
5725                (*mbx_dump_cnt)--;
5726        }
5727
5728        /* Clean out command structure on reaching dump count */
5729        if (*mbx_dump_cnt == 0)
5730                memset(&idiag, 0, sizeof(idiag));
5731        return;
5732#endif
5733}
5734
5735/* lpfc_idiag_mbxacc_dump_issue_mbox - idiag debugfs dump issue mailbox command
5736 * @phba: Pointer to HBA context object.
5737 * @dmabuf: Pointer to a DMA buffer descriptor.
5738 *
5739 * Description:
5740 * This routine dump a pass-through non-embedded mailbox command from issue
5741 * mailbox command.
5742 **/
5743void
5744lpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *phba, MAILBOX_t *pmbox)
5745{
5746#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
5747        uint32_t *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt, *mbx_mbox_cmd;
5748        char line_buf[LPFC_MBX_ACC_LBUF_SZ];
5749        int len = 0;
5750        uint32_t *pword;
5751        uint8_t *pbyte;
5752        uint32_t i, j;
5753
5754        if (idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP)
5755                return;
5756
5757        mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
5758        mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
5759        mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
5760        mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
5761
5762        if (!(*mbx_dump_map & LPFC_MBX_DMP_MBX_ALL) ||
5763            (*mbx_dump_cnt == 0) ||
5764            (*mbx_word_cnt == 0))
5765                return;
5766
5767        if ((*mbx_mbox_cmd != LPFC_MBX_ALL_CMD) &&
5768            (*mbx_mbox_cmd != pmbox->mbxCommand))
5769                return;
5770
5771        /* dump buffer content */
5772        if (*mbx_dump_map & LPFC_MBX_DMP_MBX_WORD) {
5773                pr_err("Mailbox command:0x%x dump by word:\n",
5774                       pmbox->mbxCommand);
5775                pword = (uint32_t *)pmbox;
5776                for (i = 0; i < *mbx_word_cnt; i++) {
5777                        if (!(i % 8)) {
5778                                if (i != 0)
5779                                        pr_err("%s\n", line_buf);
5780                                len = 0;
5781                                memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ);
5782                                len += scnprintf(line_buf+len,
5783                                                LPFC_MBX_ACC_LBUF_SZ-len,
5784                                                "%03d: ", i);
5785                        }
5786                        len += scnprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len,
5787                                        "%08x ",
5788                                        ((uint32_t)*pword) & 0xffffffff);
5789                        pword++;
5790                }
5791                if ((i - 1) % 8)
5792                        pr_err("%s\n", line_buf);
5793                pr_err("\n");
5794        }
5795        if (*mbx_dump_map & LPFC_MBX_DMP_MBX_BYTE) {
5796                pr_err("Mailbox command:0x%x dump by byte:\n",
5797                       pmbox->mbxCommand);
5798                pbyte = (uint8_t *)pmbox;
5799                for (i = 0; i < *mbx_word_cnt; i++) {
5800                        if (!(i % 8)) {
5801                                if (i != 0)
5802                                        pr_err("%s\n", line_buf);
5803                                len = 0;
5804                                memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ);
5805                                len += scnprintf(line_buf+len,
5806                                                LPFC_MBX_ACC_LBUF_SZ-len,
5807                                                "%03d: ", i);
5808                        }
5809                        for (j = 0; j < 4; j++) {
5810                                len += scnprintf(line_buf+len,
5811                                                LPFC_MBX_ACC_LBUF_SZ-len,
5812                                                "%02x",
5813                                                ((uint8_t)*pbyte) & 0xff);
5814                                pbyte++;
5815                        }
5816                        len += scnprintf(line_buf+len,
5817                                        LPFC_MBX_ACC_LBUF_SZ-len, " ");
5818                }
5819                if ((i - 1) % 8)
5820                        pr_err("%s\n", line_buf);
5821                pr_err("\n");
5822        }
5823        (*mbx_dump_cnt)--;
5824
5825        /* Clean out command structure on reaching dump count */
5826        if (*mbx_dump_cnt == 0)
5827                memset(&idiag, 0, sizeof(idiag));
5828        return;
5829#endif
5830}
5831
5832/**
5833 * lpfc_debugfs_initialize - Initialize debugfs for a vport
5834 * @vport: The vport pointer to initialize.
5835 *
5836 * Description:
5837 * When Debugfs is configured this routine sets up the lpfc debugfs file system.
5838 * If not already created, this routine will create the lpfc directory, and
5839 * lpfcX directory (for this HBA), and vportX directory for this vport. It will
5840 * also create each file used to access lpfc specific debugfs information.
5841 **/
5842inline void
5843lpfc_debugfs_initialize(struct lpfc_vport *vport)
5844{
5845#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
5846        struct lpfc_hba   *phba = vport->phba;
5847        char name[64];
5848        uint32_t num, i;
5849        bool pport_setup = false;
5850
5851        if (!lpfc_debugfs_enable)
5852                return;
5853
5854        /* Setup lpfc root directory */
5855        if (!lpfc_debugfs_root) {
5856                lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL);
5857                atomic_set(&lpfc_debugfs_hba_count, 0);
5858        }
5859        if (!lpfc_debugfs_start_time)
5860                lpfc_debugfs_start_time = jiffies;
5861
5862        /* Setup funcX directory for specific HBA PCI function */
5863        snprintf(name, sizeof(name), "fn%d", phba->brd_no);
5864        if (!phba->hba_debugfs_root) {
5865                pport_setup = true;
5866                phba->hba_debugfs_root =
5867                        debugfs_create_dir(name, lpfc_debugfs_root);
5868                atomic_inc(&lpfc_debugfs_hba_count);
5869                atomic_set(&phba->debugfs_vport_count, 0);
5870
5871                /* Multi-XRI pools */
5872                snprintf(name, sizeof(name), "multixripools");
5873                phba->debug_multixri_pools =
5874                        debugfs_create_file(name, S_IFREG | 0644,
5875                                            phba->hba_debugfs_root,
5876                                            phba,
5877                                            &lpfc_debugfs_op_multixripools);
5878                if (!phba->debug_multixri_pools) {
5879                        lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
5880                                         "0527 Cannot create debugfs multixripools\n");
5881                        goto debug_failed;
5882                }
5883
5884                /* Setup hbqinfo */
5885                snprintf(name, sizeof(name), "hbqinfo");
5886                phba->debug_hbqinfo =
5887                        debugfs_create_file(name, S_IFREG | 0644,
5888                                            phba->hba_debugfs_root,
5889                                            phba, &lpfc_debugfs_op_hbqinfo);
5890
5891#ifdef LPFC_HDWQ_LOCK_STAT
5892                /* Setup lockstat */
5893                snprintf(name, sizeof(name), "lockstat");
5894                phba->debug_lockstat =
5895                        debugfs_create_file(name, S_IFREG | 0644,
5896                                            phba->hba_debugfs_root,
5897                                            phba, &lpfc_debugfs_op_lockstat);
5898                if (!phba->debug_lockstat) {
5899                        lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
5900                                         "4610 Cant create debugfs lockstat\n");
5901                        goto debug_failed;
5902                }
5903#endif
5904
5905                /* Setup dumpHBASlim */
5906                if (phba->sli_rev < LPFC_SLI_REV4) {
5907                        snprintf(name, sizeof(name), "dumpHBASlim");
5908                        phba->debug_dumpHBASlim =
5909                                debugfs_create_file(name,
5910                                        S_IFREG|S_IRUGO|S_IWUSR,
5911                                        phba->hba_debugfs_root,
5912                                        phba, &lpfc_debugfs_op_dumpHBASlim);
5913                } else
5914                        phba->debug_dumpHBASlim = NULL;
5915
5916                /* Setup dumpHostSlim */
5917                if (phba->sli_rev < LPFC_SLI_REV4) {
5918                        snprintf(name, sizeof(name), "dumpHostSlim");
5919                        phba->debug_dumpHostSlim =
5920                                debugfs_create_file(name,
5921                                        S_IFREG|S_IRUGO|S_IWUSR,
5922                                        phba->hba_debugfs_root,
5923                                        phba, &lpfc_debugfs_op_dumpHostSlim);
5924                } else
5925                        phba->debug_dumpHostSlim = NULL;
5926
5927                /* Setup dumpData */
5928                snprintf(name, sizeof(name), "dumpData");
5929                phba->debug_dumpData =
5930                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5931                                 phba->hba_debugfs_root,
5932                                 phba, &lpfc_debugfs_op_dumpData);
5933
5934                /* Setup dumpDif */
5935                snprintf(name, sizeof(name), "dumpDif");
5936                phba->debug_dumpDif =
5937                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5938                                 phba->hba_debugfs_root,
5939                                 phba, &lpfc_debugfs_op_dumpDif);
5940
5941                /* Setup DIF Error Injections */
5942                snprintf(name, sizeof(name), "InjErrLBA");
5943                phba->debug_InjErrLBA =
5944                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5945                        phba->hba_debugfs_root,
5946                        phba, &lpfc_debugfs_op_dif_err);
5947                phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
5948
5949                snprintf(name, sizeof(name), "InjErrNPortID");
5950                phba->debug_InjErrNPortID =
5951                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5952                        phba->hba_debugfs_root,
5953                        phba, &lpfc_debugfs_op_dif_err);
5954
5955                snprintf(name, sizeof(name), "InjErrWWPN");
5956                phba->debug_InjErrWWPN =
5957                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5958                        phba->hba_debugfs_root,
5959                        phba, &lpfc_debugfs_op_dif_err);
5960
5961                snprintf(name, sizeof(name), "writeGuardInjErr");
5962                phba->debug_writeGuard =
5963                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5964                        phba->hba_debugfs_root,
5965                        phba, &lpfc_debugfs_op_dif_err);
5966
5967                snprintf(name, sizeof(name), "writeAppInjErr");
5968                phba->debug_writeApp =
5969                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5970                        phba->hba_debugfs_root,
5971                        phba, &lpfc_debugfs_op_dif_err);
5972
5973                snprintf(name, sizeof(name), "writeRefInjErr");
5974                phba->debug_writeRef =
5975                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5976                        phba->hba_debugfs_root,
5977                        phba, &lpfc_debugfs_op_dif_err);
5978
5979                snprintf(name, sizeof(name), "readGuardInjErr");
5980                phba->debug_readGuard =
5981                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5982                        phba->hba_debugfs_root,
5983                        phba, &lpfc_debugfs_op_dif_err);
5984
5985                snprintf(name, sizeof(name), "readAppInjErr");
5986                phba->debug_readApp =
5987                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5988                        phba->hba_debugfs_root,
5989                        phba, &lpfc_debugfs_op_dif_err);
5990
5991                snprintf(name, sizeof(name), "readRefInjErr");
5992                phba->debug_readRef =
5993                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5994                        phba->hba_debugfs_root,
5995                        phba, &lpfc_debugfs_op_dif_err);
5996
5997                /* Setup slow ring trace */
5998                if (lpfc_debugfs_max_slow_ring_trc) {
5999                        num = lpfc_debugfs_max_slow_ring_trc - 1;
6000                        if (num & lpfc_debugfs_max_slow_ring_trc) {
6001                                /* Change to be a power of 2 */
6002                                num = lpfc_debugfs_max_slow_ring_trc;
6003                                i = 0;
6004                                while (num > 1) {
6005                                        num = num >> 1;
6006                                        i++;
6007                                }
6008                                lpfc_debugfs_max_slow_ring_trc = (1 << i);
6009                                pr_err("lpfc_debugfs_max_disc_trc changed to "
6010                                       "%d\n", lpfc_debugfs_max_disc_trc);
6011                        }
6012                }
6013
6014                snprintf(name, sizeof(name), "slow_ring_trace");
6015                phba->debug_slow_ring_trc =
6016                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6017                                 phba->hba_debugfs_root,
6018                                 phba, &lpfc_debugfs_op_slow_ring_trc);
6019                if (!phba->slow_ring_trc) {
6020                        phba->slow_ring_trc = kmalloc(
6021                                (sizeof(struct lpfc_debugfs_trc) *
6022                                lpfc_debugfs_max_slow_ring_trc),
6023                                GFP_KERNEL);
6024                        if (!phba->slow_ring_trc) {
6025                                lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
6026                                                 "0416 Cannot create debugfs "
6027                                                 "slow_ring buffer\n");
6028                                goto debug_failed;
6029                        }
6030                        atomic_set(&phba->slow_ring_trc_cnt, 0);
6031                        memset(phba->slow_ring_trc, 0,
6032                                (sizeof(struct lpfc_debugfs_trc) *
6033                                lpfc_debugfs_max_slow_ring_trc));
6034                }
6035
6036                snprintf(name, sizeof(name), "nvmeio_trc");
6037                phba->debug_nvmeio_trc =
6038                        debugfs_create_file(name, 0644,
6039                                            phba->hba_debugfs_root,
6040                                            phba, &lpfc_debugfs_op_nvmeio_trc);
6041
6042                atomic_set(&phba->nvmeio_trc_cnt, 0);
6043                if (lpfc_debugfs_max_nvmeio_trc) {
6044                        num = lpfc_debugfs_max_nvmeio_trc - 1;
6045                        if (num & lpfc_debugfs_max_disc_trc) {
6046                                /* Change to be a power of 2 */
6047                                num = lpfc_debugfs_max_nvmeio_trc;
6048                                i = 0;
6049                                while (num > 1) {
6050                                        num = num >> 1;
6051                                        i++;
6052                                }
6053                                lpfc_debugfs_max_nvmeio_trc = (1 << i);
6054                                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
6055                                                "0575 lpfc_debugfs_max_nvmeio_trc "
6056                                                "changed to %d\n",
6057                                                lpfc_debugfs_max_nvmeio_trc);
6058                        }
6059                        phba->nvmeio_trc_size = lpfc_debugfs_max_nvmeio_trc;
6060
6061                        /* Allocate trace buffer and initialize */
6062                        phba->nvmeio_trc = kzalloc(
6063                                (sizeof(struct lpfc_debugfs_nvmeio_trc) *
6064                                phba->nvmeio_trc_size), GFP_KERNEL);
6065
6066                        if (!phba->nvmeio_trc) {
6067                                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
6068                                                "0576 Cannot create debugfs "
6069                                                "nvmeio_trc buffer\n");
6070                                goto nvmeio_off;
6071                        }
6072                        phba->nvmeio_trc_on = 1;
6073                        phba->nvmeio_trc_output_idx = 0;
6074                        phba->nvmeio_trc = NULL;
6075                } else {
6076nvmeio_off:
6077                        phba->nvmeio_trc_size = 0;
6078                        phba->nvmeio_trc_on = 0;
6079                        phba->nvmeio_trc_output_idx = 0;
6080                        phba->nvmeio_trc = NULL;
6081                }
6082        }
6083
6084        snprintf(name, sizeof(name), "vport%d", vport->vpi);
6085        if (!vport->vport_debugfs_root) {
6086                vport->vport_debugfs_root =
6087                        debugfs_create_dir(name, phba->hba_debugfs_root);
6088                atomic_inc(&phba->debugfs_vport_count);
6089        }
6090
6091        if (lpfc_debugfs_max_disc_trc) {
6092                num = lpfc_debugfs_max_disc_trc - 1;
6093                if (num & lpfc_debugfs_max_disc_trc) {
6094                        /* Change to be a power of 2 */
6095                        num = lpfc_debugfs_max_disc_trc;
6096                        i = 0;
6097                        while (num > 1) {
6098                                num = num >> 1;
6099                                i++;
6100                        }
6101                        lpfc_debugfs_max_disc_trc = (1 << i);
6102                        pr_err("lpfc_debugfs_max_disc_trc changed to %d\n",
6103                               lpfc_debugfs_max_disc_trc);
6104                }
6105        }
6106
6107        vport->disc_trc = kzalloc(
6108                (sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc),
6109                GFP_KERNEL);
6110
6111        if (!vport->disc_trc) {
6112                lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
6113                                 "0418 Cannot create debugfs disc trace "
6114                                 "buffer\n");
6115                goto debug_failed;
6116        }
6117        atomic_set(&vport->disc_trc_cnt, 0);
6118
6119        snprintf(name, sizeof(name), "discovery_trace");
6120        vport->debug_disc_trc =
6121                debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6122                                 vport->vport_debugfs_root,
6123                                 vport, &lpfc_debugfs_op_disc_trc);
6124        snprintf(name, sizeof(name), "nodelist");
6125        vport->debug_nodelist =
6126                debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6127                                 vport->vport_debugfs_root,
6128                                 vport, &lpfc_debugfs_op_nodelist);
6129
6130        snprintf(name, sizeof(name), "nvmestat");
6131        vport->debug_nvmestat =
6132                debugfs_create_file(name, 0644,
6133                                    vport->vport_debugfs_root,
6134                                    vport, &lpfc_debugfs_op_nvmestat);
6135
6136        snprintf(name, sizeof(name), "scsistat");
6137        vport->debug_scsistat =
6138                debugfs_create_file(name, 0644,
6139                                    vport->vport_debugfs_root,
6140                                    vport, &lpfc_debugfs_op_scsistat);
6141        if (!vport->debug_scsistat) {
6142                lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
6143                                 "4611 Cannot create debugfs scsistat\n");
6144                goto debug_failed;
6145        }
6146
6147        snprintf(name, sizeof(name), "nvmektime");
6148        vport->debug_nvmektime =
6149                debugfs_create_file(name, 0644,
6150                                    vport->vport_debugfs_root,
6151                                    vport, &lpfc_debugfs_op_nvmektime);
6152
6153        snprintf(name, sizeof(name), "cpucheck");
6154        vport->debug_cpucheck =
6155                debugfs_create_file(name, 0644,
6156                                    vport->vport_debugfs_root,
6157                                    vport, &lpfc_debugfs_op_cpucheck);
6158
6159        /*
6160         * The following section is for additional directories/files for the
6161         * physical port.
6162         */
6163
6164        if (!pport_setup)
6165                goto debug_failed;
6166
6167        /*
6168         * iDiag debugfs root entry points for SLI4 device only
6169         */
6170        if (phba->sli_rev < LPFC_SLI_REV4)
6171                goto debug_failed;
6172
6173        snprintf(name, sizeof(name), "iDiag");
6174        if (!phba->idiag_root) {
6175                phba->idiag_root =
6176                        debugfs_create_dir(name, phba->hba_debugfs_root);
6177                /* Initialize iDiag data structure */
6178                memset(&idiag, 0, sizeof(idiag));
6179        }
6180
6181        /* iDiag read PCI config space */
6182        snprintf(name, sizeof(name), "pciCfg");
6183        if (!phba->idiag_pci_cfg) {
6184                phba->idiag_pci_cfg =
6185                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6186                                phba->idiag_root, phba, &lpfc_idiag_op_pciCfg);
6187                idiag.offset.last_rd = 0;
6188        }
6189
6190        /* iDiag PCI BAR access */
6191        snprintf(name, sizeof(name), "barAcc");
6192        if (!phba->idiag_bar_acc) {
6193                phba->idiag_bar_acc =
6194                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6195                                phba->idiag_root, phba, &lpfc_idiag_op_barAcc);
6196                idiag.offset.last_rd = 0;
6197        }
6198
6199        /* iDiag get PCI function queue information */
6200        snprintf(name, sizeof(name), "queInfo");
6201        if (!phba->idiag_que_info) {
6202                phba->idiag_que_info =
6203                        debugfs_create_file(name, S_IFREG|S_IRUGO,
6204                        phba->idiag_root, phba, &lpfc_idiag_op_queInfo);
6205        }
6206
6207        /* iDiag access PCI function queue */
6208        snprintf(name, sizeof(name), "queAcc");
6209        if (!phba->idiag_que_acc) {
6210                phba->idiag_que_acc =
6211                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6212                                phba->idiag_root, phba, &lpfc_idiag_op_queAcc);
6213        }
6214
6215        /* iDiag access PCI function doorbell registers */
6216        snprintf(name, sizeof(name), "drbAcc");
6217        if (!phba->idiag_drb_acc) {
6218                phba->idiag_drb_acc =
6219                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6220                                phba->idiag_root, phba, &lpfc_idiag_op_drbAcc);
6221        }
6222
6223        /* iDiag access PCI function control registers */
6224        snprintf(name, sizeof(name), "ctlAcc");
6225        if (!phba->idiag_ctl_acc) {
6226                phba->idiag_ctl_acc =
6227                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6228                                phba->idiag_root, phba, &lpfc_idiag_op_ctlAcc);
6229        }
6230
6231        /* iDiag access mbox commands */
6232        snprintf(name, sizeof(name), "mbxAcc");
6233        if (!phba->idiag_mbx_acc) {
6234                phba->idiag_mbx_acc =
6235                        debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6236                                phba->idiag_root, phba, &lpfc_idiag_op_mbxAcc);
6237        }
6238
6239        /* iDiag extents access commands */
6240        if (phba->sli4_hba.extents_in_use) {
6241                snprintf(name, sizeof(name), "extAcc");
6242                if (!phba->idiag_ext_acc) {
6243                        phba->idiag_ext_acc =
6244                                debugfs_create_file(name,
6245                                                    S_IFREG|S_IRUGO|S_IWUSR,
6246                                                    phba->idiag_root, phba,
6247                                                    &lpfc_idiag_op_extAcc);
6248                }
6249        }
6250
6251debug_failed:
6252        return;
6253#endif
6254}
6255
6256/**
6257 * lpfc_debugfs_terminate -  Tear down debugfs infrastructure for this vport
6258 * @vport: The vport pointer to remove from debugfs.
6259 *
6260 * Description:
6261 * When Debugfs is configured this routine removes debugfs file system elements
6262 * that are specific to this vport. It also checks to see if there are any
6263 * users left for the debugfs directories associated with the HBA and driver. If
6264 * this is the last user of the HBA directory or driver directory then it will
6265 * remove those from the debugfs infrastructure as well.
6266 **/
6267inline void
6268lpfc_debugfs_terminate(struct lpfc_vport *vport)
6269{
6270#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
6271        struct lpfc_hba   *phba = vport->phba;
6272
6273        kfree(vport->disc_trc);
6274        vport->disc_trc = NULL;
6275
6276        debugfs_remove(vport->debug_disc_trc); /* discovery_trace */
6277        vport->debug_disc_trc = NULL;
6278
6279        debugfs_remove(vport->debug_nodelist); /* nodelist */
6280        vport->debug_nodelist = NULL;
6281
6282        debugfs_remove(vport->debug_nvmestat); /* nvmestat */
6283        vport->debug_nvmestat = NULL;
6284
6285        debugfs_remove(vport->debug_scsistat); /* scsistat */
6286        vport->debug_scsistat = NULL;
6287
6288        debugfs_remove(vport->debug_nvmektime); /* nvmektime */
6289        vport->debug_nvmektime = NULL;
6290
6291        debugfs_remove(vport->debug_cpucheck); /* cpucheck */
6292        vport->debug_cpucheck = NULL;
6293
6294        if (vport->vport_debugfs_root) {
6295                debugfs_remove(vport->vport_debugfs_root); /* vportX */
6296                vport->vport_debugfs_root = NULL;
6297                atomic_dec(&phba->debugfs_vport_count);
6298        }
6299
6300        if (atomic_read(&phba->debugfs_vport_count) == 0) {
6301
6302                debugfs_remove(phba->debug_multixri_pools); /* multixripools*/
6303                phba->debug_multixri_pools = NULL;
6304
6305                debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */
6306                phba->debug_hbqinfo = NULL;
6307
6308#ifdef LPFC_HDWQ_LOCK_STAT
6309                debugfs_remove(phba->debug_lockstat); /* lockstat */
6310                phba->debug_lockstat = NULL;
6311#endif
6312                debugfs_remove(phba->debug_dumpHBASlim); /* HBASlim */
6313                phba->debug_dumpHBASlim = NULL;
6314
6315                debugfs_remove(phba->debug_dumpHostSlim); /* HostSlim */
6316                phba->debug_dumpHostSlim = NULL;
6317
6318                debugfs_remove(phba->debug_dumpData); /* dumpData */
6319                phba->debug_dumpData = NULL;
6320
6321                debugfs_remove(phba->debug_dumpDif); /* dumpDif */
6322                phba->debug_dumpDif = NULL;
6323
6324                debugfs_remove(phba->debug_InjErrLBA); /* InjErrLBA */
6325                phba->debug_InjErrLBA = NULL;
6326
6327                debugfs_remove(phba->debug_InjErrNPortID);
6328                phba->debug_InjErrNPortID = NULL;
6329
6330                debugfs_remove(phba->debug_InjErrWWPN); /* InjErrWWPN */
6331                phba->debug_InjErrWWPN = NULL;
6332
6333                debugfs_remove(phba->debug_writeGuard); /* writeGuard */
6334                phba->debug_writeGuard = NULL;
6335
6336                debugfs_remove(phba->debug_writeApp); /* writeApp */
6337                phba->debug_writeApp = NULL;
6338
6339                debugfs_remove(phba->debug_writeRef); /* writeRef */
6340                phba->debug_writeRef = NULL;
6341
6342                debugfs_remove(phba->debug_readGuard); /* readGuard */
6343                phba->debug_readGuard = NULL;
6344
6345                debugfs_remove(phba->debug_readApp); /* readApp */
6346                phba->debug_readApp = NULL;
6347
6348                debugfs_remove(phba->debug_readRef); /* readRef */
6349                phba->debug_readRef = NULL;
6350
6351                kfree(phba->slow_ring_trc);
6352                phba->slow_ring_trc = NULL;
6353
6354                /* slow_ring_trace */
6355                debugfs_remove(phba->debug_slow_ring_trc);
6356                phba->debug_slow_ring_trc = NULL;
6357
6358                debugfs_remove(phba->debug_nvmeio_trc);
6359                phba->debug_nvmeio_trc = NULL;
6360
6361                kfree(phba->nvmeio_trc);
6362                phba->nvmeio_trc = NULL;
6363
6364                /*
6365                 * iDiag release
6366                 */
6367                if (phba->sli_rev == LPFC_SLI_REV4) {
6368                        /* iDiag extAcc */
6369                        debugfs_remove(phba->idiag_ext_acc);
6370                        phba->idiag_ext_acc = NULL;
6371
6372                        /* iDiag mbxAcc */
6373                        debugfs_remove(phba->idiag_mbx_acc);
6374                        phba->idiag_mbx_acc = NULL;
6375
6376                        /* iDiag ctlAcc */
6377                        debugfs_remove(phba->idiag_ctl_acc);
6378                        phba->idiag_ctl_acc = NULL;
6379
6380                        /* iDiag drbAcc */
6381                        debugfs_remove(phba->idiag_drb_acc);
6382                        phba->idiag_drb_acc = NULL;
6383
6384                        /* iDiag queAcc */
6385                        debugfs_remove(phba->idiag_que_acc);
6386                        phba->idiag_que_acc = NULL;
6387
6388                        /* iDiag queInfo */
6389                        debugfs_remove(phba->idiag_que_info);
6390                        phba->idiag_que_info = NULL;
6391
6392                        /* iDiag barAcc */
6393                        debugfs_remove(phba->idiag_bar_acc);
6394                        phba->idiag_bar_acc = NULL;
6395
6396                        /* iDiag pciCfg */
6397                        debugfs_remove(phba->idiag_pci_cfg);
6398                        phba->idiag_pci_cfg = NULL;
6399
6400                        /* Finally remove the iDiag debugfs root */
6401                        debugfs_remove(phba->idiag_root);
6402                        phba->idiag_root = NULL;
6403                }
6404
6405                if (phba->hba_debugfs_root) {
6406                        debugfs_remove(phba->hba_debugfs_root); /* fnX */
6407                        phba->hba_debugfs_root = NULL;
6408                        atomic_dec(&lpfc_debugfs_hba_count);
6409                }
6410
6411                if (atomic_read(&lpfc_debugfs_hba_count) == 0) {
6412                        debugfs_remove(lpfc_debugfs_root); /* lpfc */
6413                        lpfc_debugfs_root = NULL;
6414                }
6415        }
6416#endif
6417        return;
6418}
6419
6420/*
6421 * Driver debug utility routines outside of debugfs. The debug utility
6422 * routines implemented here is intended to be used in the instrumented
6423 * debug driver for debugging host or port issues.
6424 */
6425
6426/**
6427 * lpfc_debug_dump_all_queues - dump all the queues with a hba
6428 * @phba: Pointer to HBA context object.
6429 *
6430 * This function dumps entries of all the queues asociated with the @phba.
6431 **/
6432void
6433lpfc_debug_dump_all_queues(struct lpfc_hba *phba)
6434{
6435        int idx;
6436
6437        /*
6438         * Dump Work Queues (WQs)
6439         */
6440        lpfc_debug_dump_wq(phba, DUMP_MBX, 0);
6441        lpfc_debug_dump_wq(phba, DUMP_ELS, 0);
6442        lpfc_debug_dump_wq(phba, DUMP_NVMELS, 0);
6443
6444        for (idx = 0; idx < phba->cfg_hdw_queue; idx++)
6445                lpfc_debug_dump_wq(phba, DUMP_FCP, idx);
6446
6447        if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) {
6448                for (idx = 0; idx < phba->cfg_hdw_queue; idx++)
6449                        lpfc_debug_dump_wq(phba, DUMP_NVME, idx);
6450        }
6451
6452        lpfc_debug_dump_hdr_rq(phba);
6453        lpfc_debug_dump_dat_rq(phba);
6454        /*
6455         * Dump Complete Queues (CQs)
6456         */
6457        lpfc_debug_dump_cq(phba, DUMP_MBX, 0);
6458        lpfc_debug_dump_cq(phba, DUMP_ELS, 0);
6459        lpfc_debug_dump_cq(phba, DUMP_NVMELS, 0);
6460
6461        for (idx = 0; idx < phba->cfg_hdw_queue; idx++)
6462                lpfc_debug_dump_cq(phba, DUMP_FCP, idx);
6463
6464        if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) {
6465                for (idx = 0; idx < phba->cfg_hdw_queue; idx++)
6466                        lpfc_debug_dump_cq(phba, DUMP_NVME, idx);
6467        }
6468
6469        /*
6470         * Dump Event Queues (EQs)
6471         */
6472        for (idx = 0; idx < phba->cfg_hdw_queue; idx++)
6473                lpfc_debug_dump_hba_eq(phba, idx);
6474}
6475