162306a36Sopenharmony_ci/*******************************************************************
262306a36Sopenharmony_ci * This file is part of the Emulex Linux Device Driver for         *
362306a36Sopenharmony_ci * Fibre Channel Host Bus Adapters.                                *
462306a36Sopenharmony_ci * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term *
562306a36Sopenharmony_ci * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.  *
662306a36Sopenharmony_ci * Copyright (C) 2007-2015 Emulex.  All rights reserved.           *
762306a36Sopenharmony_ci * EMULEX and SLI are trademarks of Emulex.                        *
862306a36Sopenharmony_ci * www.broadcom.com                                                *
962306a36Sopenharmony_ci *                                                                 *
1062306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or   *
1162306a36Sopenharmony_ci * modify it under the terms of version 2 of the GNU General       *
1262306a36Sopenharmony_ci * Public License as published by the Free Software Foundation.    *
1362306a36Sopenharmony_ci * This program is distributed in the hope that it will be useful. *
1462306a36Sopenharmony_ci * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
1562306a36Sopenharmony_ci * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
1662306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
1762306a36Sopenharmony_ci * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
1862306a36Sopenharmony_ci * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
1962306a36Sopenharmony_ci * more details, a copy of which can be found in the file COPYING  *
2062306a36Sopenharmony_ci * included with this package.                                     *
2162306a36Sopenharmony_ci *******************************************************************/
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#include <linux/blkdev.h>
2462306a36Sopenharmony_ci#include <linux/delay.h>
2562306a36Sopenharmony_ci#include <linux/module.h>
2662306a36Sopenharmony_ci#include <linux/dma-mapping.h>
2762306a36Sopenharmony_ci#include <linux/idr.h>
2862306a36Sopenharmony_ci#include <linux/interrupt.h>
2962306a36Sopenharmony_ci#include <linux/kthread.h>
3062306a36Sopenharmony_ci#include <linux/slab.h>
3162306a36Sopenharmony_ci#include <linux/pci.h>
3262306a36Sopenharmony_ci#include <linux/spinlock.h>
3362306a36Sopenharmony_ci#include <linux/ctype.h>
3462306a36Sopenharmony_ci#include <linux/vmalloc.h>
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#include <scsi/scsi.h>
3762306a36Sopenharmony_ci#include <scsi/scsi_device.h>
3862306a36Sopenharmony_ci#include <scsi/scsi_host.h>
3962306a36Sopenharmony_ci#include <scsi/scsi_transport_fc.h>
4062306a36Sopenharmony_ci#include <scsi/fc/fc_fs.h>
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#include "lpfc_hw4.h"
4362306a36Sopenharmony_ci#include "lpfc_hw.h"
4462306a36Sopenharmony_ci#include "lpfc_sli.h"
4562306a36Sopenharmony_ci#include "lpfc_sli4.h"
4662306a36Sopenharmony_ci#include "lpfc_nl.h"
4762306a36Sopenharmony_ci#include "lpfc_disc.h"
4862306a36Sopenharmony_ci#include "lpfc.h"
4962306a36Sopenharmony_ci#include "lpfc_scsi.h"
5062306a36Sopenharmony_ci#include "lpfc_nvme.h"
5162306a36Sopenharmony_ci#include "lpfc_logmsg.h"
5262306a36Sopenharmony_ci#include "lpfc_crtn.h"
5362306a36Sopenharmony_ci#include "lpfc_vport.h"
5462306a36Sopenharmony_ci#include "lpfc_version.h"
5562306a36Sopenharmony_ci#include "lpfc_compat.h"
5662306a36Sopenharmony_ci#include "lpfc_debugfs.h"
5762306a36Sopenharmony_ci#include "lpfc_bsg.h"
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
6062306a36Sopenharmony_ci/*
6162306a36Sopenharmony_ci * debugfs interface
6262306a36Sopenharmony_ci *
6362306a36Sopenharmony_ci * To access this interface the user should:
6462306a36Sopenharmony_ci * # mount -t debugfs none /sys/kernel/debug
6562306a36Sopenharmony_ci *
6662306a36Sopenharmony_ci * The lpfc debugfs directory hierarchy is:
6762306a36Sopenharmony_ci * /sys/kernel/debug/lpfc/fnX/vportY
6862306a36Sopenharmony_ci * where X is the lpfc hba function unique_id
6962306a36Sopenharmony_ci * where Y is the vport VPI on that hba
7062306a36Sopenharmony_ci *
7162306a36Sopenharmony_ci * Debugging services available per vport:
7262306a36Sopenharmony_ci * discovery_trace
7362306a36Sopenharmony_ci * This is an ACSII readable file that contains a trace of the last
7462306a36Sopenharmony_ci * lpfc_debugfs_max_disc_trc events that happened on a specific vport.
7562306a36Sopenharmony_ci * See lpfc_debugfs.h for different categories of  discovery events.
7662306a36Sopenharmony_ci * To enable the discovery trace, the following module parameters must be set:
7762306a36Sopenharmony_ci * lpfc_debugfs_enable=1         Turns on lpfc debugfs filesystem support
7862306a36Sopenharmony_ci * lpfc_debugfs_max_disc_trc=X   Where X is the event trace depth for
7962306a36Sopenharmony_ci *                               EACH vport. X MUST also be a power of 2.
8062306a36Sopenharmony_ci * lpfc_debugfs_mask_disc_trc=Y  Where Y is an event mask as defined in
8162306a36Sopenharmony_ci *                               lpfc_debugfs.h .
8262306a36Sopenharmony_ci *
8362306a36Sopenharmony_ci * slow_ring_trace
8462306a36Sopenharmony_ci * This is an ACSII readable file that contains a trace of the last
8562306a36Sopenharmony_ci * lpfc_debugfs_max_slow_ring_trc events that happened on a specific HBA.
8662306a36Sopenharmony_ci * To enable the slow ring trace, the following module parameters must be set:
8762306a36Sopenharmony_ci * lpfc_debugfs_enable=1         Turns on lpfc debugfs filesystem support
8862306a36Sopenharmony_ci * lpfc_debugfs_max_slow_ring_trc=X   Where X is the event trace depth for
8962306a36Sopenharmony_ci *                               the HBA. X MUST also be a power of 2.
9062306a36Sopenharmony_ci */
9162306a36Sopenharmony_cistatic int lpfc_debugfs_enable = 1;
9262306a36Sopenharmony_cimodule_param(lpfc_debugfs_enable, int, S_IRUGO);
9362306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services");
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/* This MUST be a power of 2 */
9662306a36Sopenharmony_cistatic int lpfc_debugfs_max_disc_trc;
9762306a36Sopenharmony_cimodule_param(lpfc_debugfs_max_disc_trc, int, S_IRUGO);
9862306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_debugfs_max_disc_trc,
9962306a36Sopenharmony_ci	"Set debugfs discovery trace depth");
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci/* This MUST be a power of 2 */
10262306a36Sopenharmony_cistatic int lpfc_debugfs_max_slow_ring_trc;
10362306a36Sopenharmony_cimodule_param(lpfc_debugfs_max_slow_ring_trc, int, S_IRUGO);
10462306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc,
10562306a36Sopenharmony_ci	"Set debugfs slow ring trace depth");
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci/* This MUST be a power of 2 */
10862306a36Sopenharmony_cistatic int lpfc_debugfs_max_nvmeio_trc;
10962306a36Sopenharmony_cimodule_param(lpfc_debugfs_max_nvmeio_trc, int, 0444);
11062306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_debugfs_max_nvmeio_trc,
11162306a36Sopenharmony_ci		 "Set debugfs NVME IO trace depth");
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_cistatic int lpfc_debugfs_mask_disc_trc;
11462306a36Sopenharmony_cimodule_param(lpfc_debugfs_mask_disc_trc, int, S_IRUGO);
11562306a36Sopenharmony_ciMODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc,
11662306a36Sopenharmony_ci	"Set debugfs discovery trace mask");
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci#include <linux/debugfs.h>
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistatic atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0);
12162306a36Sopenharmony_cistatic unsigned long lpfc_debugfs_start_time = 0L;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci/* iDiag */
12462306a36Sopenharmony_cistatic struct lpfc_idiag idiag;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci/**
12762306a36Sopenharmony_ci * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer
12862306a36Sopenharmony_ci * @vport: The vport to gather the log info from.
12962306a36Sopenharmony_ci * @buf: The buffer to dump log into.
13062306a36Sopenharmony_ci * @size: The maximum amount of data to process.
13162306a36Sopenharmony_ci *
13262306a36Sopenharmony_ci * Description:
13362306a36Sopenharmony_ci * This routine gathers the lpfc discovery debugfs data from the @vport and
13462306a36Sopenharmony_ci * dumps it to @buf up to @size number of bytes. It will start at the next entry
13562306a36Sopenharmony_ci * in the log and process the log until the end of the buffer. Then it will
13662306a36Sopenharmony_ci * gather from the beginning of the log and process until the current entry.
13762306a36Sopenharmony_ci *
13862306a36Sopenharmony_ci * Notes:
13962306a36Sopenharmony_ci * Discovery logging will be disabled while while this routine dumps the log.
14062306a36Sopenharmony_ci *
14162306a36Sopenharmony_ci * Return Value:
14262306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will
14362306a36Sopenharmony_ci * not exceed @size.
14462306a36Sopenharmony_ci **/
14562306a36Sopenharmony_cistatic int
14662306a36Sopenharmony_cilpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	int i, index, len, enable;
14962306a36Sopenharmony_ci	uint32_t ms;
15062306a36Sopenharmony_ci	struct lpfc_debugfs_trc *dtp;
15162306a36Sopenharmony_ci	char *buffer;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL);
15462306a36Sopenharmony_ci	if (!buffer)
15562306a36Sopenharmony_ci		return 0;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	enable = lpfc_debugfs_enable;
15862306a36Sopenharmony_ci	lpfc_debugfs_enable = 0;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	len = 0;
16162306a36Sopenharmony_ci	index = (atomic_read(&vport->disc_trc_cnt) + 1) &
16262306a36Sopenharmony_ci		(lpfc_debugfs_max_disc_trc - 1);
16362306a36Sopenharmony_ci	for (i = index; i < lpfc_debugfs_max_disc_trc; i++) {
16462306a36Sopenharmony_ci		dtp = vport->disc_trc + i;
16562306a36Sopenharmony_ci		if (!dtp->fmt)
16662306a36Sopenharmony_ci			continue;
16762306a36Sopenharmony_ci		ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
16862306a36Sopenharmony_ci		snprintf(buffer,
16962306a36Sopenharmony_ci			LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
17062306a36Sopenharmony_ci			dtp->seq_cnt, ms, dtp->fmt);
17162306a36Sopenharmony_ci		len +=  scnprintf(buf+len, size-len, buffer,
17262306a36Sopenharmony_ci			dtp->data1, dtp->data2, dtp->data3);
17362306a36Sopenharmony_ci	}
17462306a36Sopenharmony_ci	for (i = 0; i < index; i++) {
17562306a36Sopenharmony_ci		dtp = vport->disc_trc + i;
17662306a36Sopenharmony_ci		if (!dtp->fmt)
17762306a36Sopenharmony_ci			continue;
17862306a36Sopenharmony_ci		ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
17962306a36Sopenharmony_ci		snprintf(buffer,
18062306a36Sopenharmony_ci			LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
18162306a36Sopenharmony_ci			dtp->seq_cnt, ms, dtp->fmt);
18262306a36Sopenharmony_ci		len +=  scnprintf(buf+len, size-len, buffer,
18362306a36Sopenharmony_ci			dtp->data1, dtp->data2, dtp->data3);
18462306a36Sopenharmony_ci	}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	lpfc_debugfs_enable = enable;
18762306a36Sopenharmony_ci	kfree(buffer);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	return len;
19062306a36Sopenharmony_ci}
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci/**
19362306a36Sopenharmony_ci * lpfc_debugfs_slow_ring_trc_data - Dump slow ring logging to a buffer
19462306a36Sopenharmony_ci * @phba: The HBA to gather the log info from.
19562306a36Sopenharmony_ci * @buf: The buffer to dump log into.
19662306a36Sopenharmony_ci * @size: The maximum amount of data to process.
19762306a36Sopenharmony_ci *
19862306a36Sopenharmony_ci * Description:
19962306a36Sopenharmony_ci * This routine gathers the lpfc slow ring debugfs data from the @phba and
20062306a36Sopenharmony_ci * dumps it to @buf up to @size number of bytes. It will start at the next entry
20162306a36Sopenharmony_ci * in the log and process the log until the end of the buffer. Then it will
20262306a36Sopenharmony_ci * gather from the beginning of the log and process until the current entry.
20362306a36Sopenharmony_ci *
20462306a36Sopenharmony_ci * Notes:
20562306a36Sopenharmony_ci * Slow ring logging will be disabled while while this routine dumps the log.
20662306a36Sopenharmony_ci *
20762306a36Sopenharmony_ci * Return Value:
20862306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will
20962306a36Sopenharmony_ci * not exceed @size.
21062306a36Sopenharmony_ci **/
21162306a36Sopenharmony_cistatic int
21262306a36Sopenharmony_cilpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	int i, index, len, enable;
21562306a36Sopenharmony_ci	uint32_t ms;
21662306a36Sopenharmony_ci	struct lpfc_debugfs_trc *dtp;
21762306a36Sopenharmony_ci	char *buffer;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL);
22062306a36Sopenharmony_ci	if (!buffer)
22162306a36Sopenharmony_ci		return 0;
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	enable = lpfc_debugfs_enable;
22462306a36Sopenharmony_ci	lpfc_debugfs_enable = 0;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	len = 0;
22762306a36Sopenharmony_ci	index = (atomic_read(&phba->slow_ring_trc_cnt) + 1) &
22862306a36Sopenharmony_ci		(lpfc_debugfs_max_slow_ring_trc - 1);
22962306a36Sopenharmony_ci	for (i = index; i < lpfc_debugfs_max_slow_ring_trc; i++) {
23062306a36Sopenharmony_ci		dtp = phba->slow_ring_trc + i;
23162306a36Sopenharmony_ci		if (!dtp->fmt)
23262306a36Sopenharmony_ci			continue;
23362306a36Sopenharmony_ci		ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
23462306a36Sopenharmony_ci		snprintf(buffer,
23562306a36Sopenharmony_ci			LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
23662306a36Sopenharmony_ci			dtp->seq_cnt, ms, dtp->fmt);
23762306a36Sopenharmony_ci		len +=  scnprintf(buf+len, size-len, buffer,
23862306a36Sopenharmony_ci			dtp->data1, dtp->data2, dtp->data3);
23962306a36Sopenharmony_ci	}
24062306a36Sopenharmony_ci	for (i = 0; i < index; i++) {
24162306a36Sopenharmony_ci		dtp = phba->slow_ring_trc + i;
24262306a36Sopenharmony_ci		if (!dtp->fmt)
24362306a36Sopenharmony_ci			continue;
24462306a36Sopenharmony_ci		ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
24562306a36Sopenharmony_ci		snprintf(buffer,
24662306a36Sopenharmony_ci			LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
24762306a36Sopenharmony_ci			dtp->seq_cnt, ms, dtp->fmt);
24862306a36Sopenharmony_ci		len +=  scnprintf(buf+len, size-len, buffer,
24962306a36Sopenharmony_ci			dtp->data1, dtp->data2, dtp->data3);
25062306a36Sopenharmony_ci	}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	lpfc_debugfs_enable = enable;
25362306a36Sopenharmony_ci	kfree(buffer);
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	return len;
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cistatic int lpfc_debugfs_last_hbq = -1;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci/**
26162306a36Sopenharmony_ci * lpfc_debugfs_hbqinfo_data - Dump host buffer queue info to a buffer
26262306a36Sopenharmony_ci * @phba: The HBA to gather host buffer info from.
26362306a36Sopenharmony_ci * @buf: The buffer to dump log into.
26462306a36Sopenharmony_ci * @size: The maximum amount of data to process.
26562306a36Sopenharmony_ci *
26662306a36Sopenharmony_ci * Description:
26762306a36Sopenharmony_ci * This routine dumps the host buffer queue info from the @phba to @buf up to
26862306a36Sopenharmony_ci * @size number of bytes. A header that describes the current hbq state will be
26962306a36Sopenharmony_ci * dumped to @buf first and then info on each hbq entry will be dumped to @buf
27062306a36Sopenharmony_ci * until @size bytes have been dumped or all the hbq info has been dumped.
27162306a36Sopenharmony_ci *
27262306a36Sopenharmony_ci * Notes:
27362306a36Sopenharmony_ci * This routine will rotate through each configured HBQ each time called.
27462306a36Sopenharmony_ci *
27562306a36Sopenharmony_ci * Return Value:
27662306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will
27762306a36Sopenharmony_ci * not exceed @size.
27862306a36Sopenharmony_ci **/
27962306a36Sopenharmony_cistatic int
28062306a36Sopenharmony_cilpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	int len = 0;
28362306a36Sopenharmony_ci	int i, j, found, posted, low;
28462306a36Sopenharmony_ci	uint32_t phys, raw_index, getidx;
28562306a36Sopenharmony_ci	struct lpfc_hbq_init *hip;
28662306a36Sopenharmony_ci	struct hbq_s *hbqs;
28762306a36Sopenharmony_ci	struct lpfc_hbq_entry *hbqe;
28862306a36Sopenharmony_ci	struct lpfc_dmabuf *d_buf;
28962306a36Sopenharmony_ci	struct hbq_dmabuf *hbq_buf;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	if (phba->sli_rev != 3)
29262306a36Sopenharmony_ci		return 0;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	spin_lock_irq(&phba->hbalock);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	/* toggle between multiple hbqs, if any */
29762306a36Sopenharmony_ci	i = lpfc_sli_hbq_count();
29862306a36Sopenharmony_ci	if (i > 1) {
29962306a36Sopenharmony_ci		 lpfc_debugfs_last_hbq++;
30062306a36Sopenharmony_ci		 if (lpfc_debugfs_last_hbq >= i)
30162306a36Sopenharmony_ci			lpfc_debugfs_last_hbq = 0;
30262306a36Sopenharmony_ci	}
30362306a36Sopenharmony_ci	else
30462306a36Sopenharmony_ci		lpfc_debugfs_last_hbq = 0;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	i = lpfc_debugfs_last_hbq;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	len +=  scnprintf(buf+len, size-len, "HBQ %d Info\n", i);
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	hbqs =  &phba->hbqs[i];
31162306a36Sopenharmony_ci	posted = 0;
31262306a36Sopenharmony_ci	list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list)
31362306a36Sopenharmony_ci		posted++;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	hip =  lpfc_hbq_defs[i];
31662306a36Sopenharmony_ci	len +=  scnprintf(buf+len, size-len,
31762306a36Sopenharmony_ci		"idx:%d prof:%d rn:%d bufcnt:%d icnt:%d acnt:%d posted %d\n",
31862306a36Sopenharmony_ci		hip->hbq_index, hip->profile, hip->rn,
31962306a36Sopenharmony_ci		hip->buffer_count, hip->init_count, hip->add_count, posted);
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	raw_index = phba->hbq_get[i];
32262306a36Sopenharmony_ci	getidx = le32_to_cpu(raw_index);
32362306a36Sopenharmony_ci	len +=  scnprintf(buf+len, size-len,
32462306a36Sopenharmony_ci		"entries:%d bufcnt:%d Put:%d nPut:%d localGet:%d hbaGet:%d\n",
32562306a36Sopenharmony_ci		hbqs->entry_count, hbqs->buffer_count, hbqs->hbqPutIdx,
32662306a36Sopenharmony_ci		hbqs->next_hbqPutIdx, hbqs->local_hbqGetIdx, getidx);
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	hbqe = (struct lpfc_hbq_entry *) phba->hbqs[i].hbq_virt;
32962306a36Sopenharmony_ci	for (j=0; j<hbqs->entry_count; j++) {
33062306a36Sopenharmony_ci		len +=  scnprintf(buf+len, size-len,
33162306a36Sopenharmony_ci			"%03d: %08x %04x %05x ", j,
33262306a36Sopenharmony_ci			le32_to_cpu(hbqe->bde.addrLow),
33362306a36Sopenharmony_ci			le32_to_cpu(hbqe->bde.tus.w),
33462306a36Sopenharmony_ci			le32_to_cpu(hbqe->buffer_tag));
33562306a36Sopenharmony_ci		i = 0;
33662306a36Sopenharmony_ci		found = 0;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci		/* First calculate if slot has an associated posted buffer */
33962306a36Sopenharmony_ci		low = hbqs->hbqPutIdx - posted;
34062306a36Sopenharmony_ci		if (low >= 0) {
34162306a36Sopenharmony_ci			if ((j >= hbqs->hbqPutIdx) || (j < low)) {
34262306a36Sopenharmony_ci				len +=  scnprintf(buf + len, size - len,
34362306a36Sopenharmony_ci						"Unused\n");
34462306a36Sopenharmony_ci				goto skipit;
34562306a36Sopenharmony_ci			}
34662306a36Sopenharmony_ci		}
34762306a36Sopenharmony_ci		else {
34862306a36Sopenharmony_ci			if ((j >= hbqs->hbqPutIdx) &&
34962306a36Sopenharmony_ci				(j < (hbqs->entry_count+low))) {
35062306a36Sopenharmony_ci				len +=  scnprintf(buf + len, size - len,
35162306a36Sopenharmony_ci						"Unused\n");
35262306a36Sopenharmony_ci				goto skipit;
35362306a36Sopenharmony_ci			}
35462306a36Sopenharmony_ci		}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci		/* Get the Buffer info for the posted buffer */
35762306a36Sopenharmony_ci		list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list) {
35862306a36Sopenharmony_ci			hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf);
35962306a36Sopenharmony_ci			phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff);
36062306a36Sopenharmony_ci			if (phys == le32_to_cpu(hbqe->bde.addrLow)) {
36162306a36Sopenharmony_ci				len +=  scnprintf(buf+len, size-len,
36262306a36Sopenharmony_ci					"Buf%d: x%px %06x\n", i,
36362306a36Sopenharmony_ci					hbq_buf->dbuf.virt, hbq_buf->tag);
36462306a36Sopenharmony_ci				found = 1;
36562306a36Sopenharmony_ci				break;
36662306a36Sopenharmony_ci			}
36762306a36Sopenharmony_ci			i++;
36862306a36Sopenharmony_ci		}
36962306a36Sopenharmony_ci		if (!found) {
37062306a36Sopenharmony_ci			len +=  scnprintf(buf+len, size-len, "No DMAinfo?\n");
37162306a36Sopenharmony_ci		}
37262306a36Sopenharmony_ciskipit:
37362306a36Sopenharmony_ci		hbqe++;
37462306a36Sopenharmony_ci		if (len > LPFC_HBQINFO_SIZE - 54)
37562306a36Sopenharmony_ci			break;
37662306a36Sopenharmony_ci	}
37762306a36Sopenharmony_ci	spin_unlock_irq(&phba->hbalock);
37862306a36Sopenharmony_ci	return len;
37962306a36Sopenharmony_ci}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_cistatic int lpfc_debugfs_last_xripool;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci/**
38462306a36Sopenharmony_ci * lpfc_debugfs_commonxripools_data - Dump Hardware Queue info to a buffer
38562306a36Sopenharmony_ci * @phba: The HBA to gather host buffer info from.
38662306a36Sopenharmony_ci * @buf: The buffer to dump log into.
38762306a36Sopenharmony_ci * @size: The maximum amount of data to process.
38862306a36Sopenharmony_ci *
38962306a36Sopenharmony_ci * Description:
39062306a36Sopenharmony_ci * This routine dumps the Hardware Queue info from the @phba to @buf up to
39162306a36Sopenharmony_ci * @size number of bytes. A header that describes the current hdwq state will be
39262306a36Sopenharmony_ci * dumped to @buf first and then info on each hdwq entry will be dumped to @buf
39362306a36Sopenharmony_ci * until @size bytes have been dumped or all the hdwq info has been dumped.
39462306a36Sopenharmony_ci *
39562306a36Sopenharmony_ci * Notes:
39662306a36Sopenharmony_ci * This routine will rotate through each configured Hardware Queue each
39762306a36Sopenharmony_ci * time called.
39862306a36Sopenharmony_ci *
39962306a36Sopenharmony_ci * Return Value:
40062306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will
40162306a36Sopenharmony_ci * not exceed @size.
40262306a36Sopenharmony_ci **/
40362306a36Sopenharmony_cistatic int
40462306a36Sopenharmony_cilpfc_debugfs_commonxripools_data(struct lpfc_hba *phba, char *buf, int size)
40562306a36Sopenharmony_ci{
40662306a36Sopenharmony_ci	struct lpfc_sli4_hdw_queue *qp;
40762306a36Sopenharmony_ci	int len = 0;
40862306a36Sopenharmony_ci	int i, out;
40962306a36Sopenharmony_ci	unsigned long iflag;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	for (i = 0; i < phba->cfg_hdw_queue; i++) {
41262306a36Sopenharmony_ci		if (len > (LPFC_DUMP_MULTIXRIPOOL_SIZE - 80))
41362306a36Sopenharmony_ci			break;
41462306a36Sopenharmony_ci		qp = &phba->sli4_hba.hdwq[lpfc_debugfs_last_xripool];
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len, "HdwQ %d Info ", i);
41762306a36Sopenharmony_ci		spin_lock_irqsave(&qp->abts_io_buf_list_lock, iflag);
41862306a36Sopenharmony_ci		spin_lock(&qp->io_buf_list_get_lock);
41962306a36Sopenharmony_ci		spin_lock(&qp->io_buf_list_put_lock);
42062306a36Sopenharmony_ci		out = qp->total_io_bufs - (qp->get_io_bufs + qp->put_io_bufs +
42162306a36Sopenharmony_ci			qp->abts_scsi_io_bufs + qp->abts_nvme_io_bufs);
42262306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
42362306a36Sopenharmony_ci				 "tot:%d get:%d put:%d mt:%d "
42462306a36Sopenharmony_ci				 "ABTS scsi:%d nvme:%d Out:%d\n",
42562306a36Sopenharmony_ci			qp->total_io_bufs, qp->get_io_bufs, qp->put_io_bufs,
42662306a36Sopenharmony_ci			qp->empty_io_bufs, qp->abts_scsi_io_bufs,
42762306a36Sopenharmony_ci			qp->abts_nvme_io_bufs, out);
42862306a36Sopenharmony_ci		spin_unlock(&qp->io_buf_list_put_lock);
42962306a36Sopenharmony_ci		spin_unlock(&qp->io_buf_list_get_lock);
43062306a36Sopenharmony_ci		spin_unlock_irqrestore(&qp->abts_io_buf_list_lock, iflag);
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci		lpfc_debugfs_last_xripool++;
43362306a36Sopenharmony_ci		if (lpfc_debugfs_last_xripool >= phba->cfg_hdw_queue)
43462306a36Sopenharmony_ci			lpfc_debugfs_last_xripool = 0;
43562306a36Sopenharmony_ci	}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	return len;
43862306a36Sopenharmony_ci}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci/**
44162306a36Sopenharmony_ci * lpfc_debugfs_multixripools_data - Display multi-XRI pools information
44262306a36Sopenharmony_ci * @phba: The HBA to gather host buffer info from.
44362306a36Sopenharmony_ci * @buf: The buffer to dump log into.
44462306a36Sopenharmony_ci * @size: The maximum amount of data to process.
44562306a36Sopenharmony_ci *
44662306a36Sopenharmony_ci * Description:
44762306a36Sopenharmony_ci * This routine displays current multi-XRI pools information including XRI
44862306a36Sopenharmony_ci * count in public, private and txcmplq. It also displays current high and
44962306a36Sopenharmony_ci * low watermark.
45062306a36Sopenharmony_ci *
45162306a36Sopenharmony_ci * Return Value:
45262306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will
45362306a36Sopenharmony_ci * not exceed @size.
45462306a36Sopenharmony_ci **/
45562306a36Sopenharmony_cistatic int
45662306a36Sopenharmony_cilpfc_debugfs_multixripools_data(struct lpfc_hba *phba, char *buf, int size)
45762306a36Sopenharmony_ci{
45862306a36Sopenharmony_ci	u32 i;
45962306a36Sopenharmony_ci	u32 hwq_count;
46062306a36Sopenharmony_ci	struct lpfc_sli4_hdw_queue *qp;
46162306a36Sopenharmony_ci	struct lpfc_multixri_pool *multixri_pool;
46262306a36Sopenharmony_ci	struct lpfc_pvt_pool *pvt_pool;
46362306a36Sopenharmony_ci	struct lpfc_pbl_pool *pbl_pool;
46462306a36Sopenharmony_ci	u32 txcmplq_cnt;
46562306a36Sopenharmony_ci	char tmp[LPFC_DEBUG_OUT_LINE_SZ] = {0};
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	if (phba->sli_rev != LPFC_SLI_REV4)
46862306a36Sopenharmony_ci		return 0;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	if (!phba->sli4_hba.hdwq)
47162306a36Sopenharmony_ci		return 0;
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	if (!phba->cfg_xri_rebalancing) {
47462306a36Sopenharmony_ci		i = lpfc_debugfs_commonxripools_data(phba, buf, size);
47562306a36Sopenharmony_ci		return i;
47662306a36Sopenharmony_ci	}
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	/*
47962306a36Sopenharmony_ci	 * Pbl: Current number of free XRIs in public pool
48062306a36Sopenharmony_ci	 * Pvt: Current number of free XRIs in private pool
48162306a36Sopenharmony_ci	 * Busy: Current number of outstanding XRIs
48262306a36Sopenharmony_ci	 * HWM: Current high watermark
48362306a36Sopenharmony_ci	 * pvt_empty: Incremented by 1 when IO submission fails (no xri)
48462306a36Sopenharmony_ci	 * pbl_empty: Incremented by 1 when all pbl_pool are empty during
48562306a36Sopenharmony_ci	 *            IO submission
48662306a36Sopenharmony_ci	 */
48762306a36Sopenharmony_ci	scnprintf(tmp, sizeof(tmp),
48862306a36Sopenharmony_ci		  "HWQ:  Pbl  Pvt Busy  HWM |  pvt_empty  pbl_empty ");
48962306a36Sopenharmony_ci	if (strlcat(buf, tmp, size) >= size)
49062306a36Sopenharmony_ci		return strnlen(buf, size);
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci#ifdef LPFC_MXP_STAT
49362306a36Sopenharmony_ci	/*
49462306a36Sopenharmony_ci	 * MAXH: Max high watermark seen so far
49562306a36Sopenharmony_ci	 * above_lmt: Incremented by 1 if xri_owned > xri_limit during
49662306a36Sopenharmony_ci	 *            IO submission
49762306a36Sopenharmony_ci	 * below_lmt: Incremented by 1 if xri_owned <= xri_limit  during
49862306a36Sopenharmony_ci	 *            IO submission
49962306a36Sopenharmony_ci	 * locPbl_hit: Incremented by 1 if successfully get a batch of XRI from
50062306a36Sopenharmony_ci	 *             local pbl_pool
50162306a36Sopenharmony_ci	 * othPbl_hit: Incremented by 1 if successfully get a batch of XRI from
50262306a36Sopenharmony_ci	 *             other pbl_pool
50362306a36Sopenharmony_ci	 */
50462306a36Sopenharmony_ci	scnprintf(tmp, sizeof(tmp),
50562306a36Sopenharmony_ci		  "MAXH  above_lmt  below_lmt locPbl_hit othPbl_hit");
50662306a36Sopenharmony_ci	if (strlcat(buf, tmp, size) >= size)
50762306a36Sopenharmony_ci		return strnlen(buf, size);
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	/*
51062306a36Sopenharmony_ci	 * sPbl: snapshot of Pbl 15 sec after stat gets cleared
51162306a36Sopenharmony_ci	 * sPvt: snapshot of Pvt 15 sec after stat gets cleared
51262306a36Sopenharmony_ci	 * sBusy: snapshot of Busy 15 sec after stat gets cleared
51362306a36Sopenharmony_ci	 */
51462306a36Sopenharmony_ci	scnprintf(tmp, sizeof(tmp),
51562306a36Sopenharmony_ci		  " | sPbl sPvt sBusy");
51662306a36Sopenharmony_ci	if (strlcat(buf, tmp, size) >= size)
51762306a36Sopenharmony_ci		return strnlen(buf, size);
51862306a36Sopenharmony_ci#endif
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	scnprintf(tmp, sizeof(tmp), "\n");
52162306a36Sopenharmony_ci	if (strlcat(buf, tmp, size) >= size)
52262306a36Sopenharmony_ci		return strnlen(buf, size);
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	hwq_count = phba->cfg_hdw_queue;
52562306a36Sopenharmony_ci	for (i = 0; i < hwq_count; i++) {
52662306a36Sopenharmony_ci		qp = &phba->sli4_hba.hdwq[i];
52762306a36Sopenharmony_ci		multixri_pool = qp->p_multixri_pool;
52862306a36Sopenharmony_ci		if (!multixri_pool)
52962306a36Sopenharmony_ci			continue;
53062306a36Sopenharmony_ci		pbl_pool = &multixri_pool->pbl_pool;
53162306a36Sopenharmony_ci		pvt_pool = &multixri_pool->pvt_pool;
53262306a36Sopenharmony_ci		txcmplq_cnt = qp->io_wq->pring->txcmplq_cnt;
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci		scnprintf(tmp, sizeof(tmp),
53562306a36Sopenharmony_ci			  "%03d: %4d %4d %4d %4d | %10d %10d ",
53662306a36Sopenharmony_ci			  i, pbl_pool->count, pvt_pool->count,
53762306a36Sopenharmony_ci			  txcmplq_cnt, pvt_pool->high_watermark,
53862306a36Sopenharmony_ci			  qp->empty_io_bufs, multixri_pool->pbl_empty_count);
53962306a36Sopenharmony_ci		if (strlcat(buf, tmp, size) >= size)
54062306a36Sopenharmony_ci			break;
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci#ifdef LPFC_MXP_STAT
54362306a36Sopenharmony_ci		scnprintf(tmp, sizeof(tmp),
54462306a36Sopenharmony_ci			  "%4d %10d %10d %10d %10d",
54562306a36Sopenharmony_ci			  multixri_pool->stat_max_hwm,
54662306a36Sopenharmony_ci			  multixri_pool->above_limit_count,
54762306a36Sopenharmony_ci			  multixri_pool->below_limit_count,
54862306a36Sopenharmony_ci			  multixri_pool->local_pbl_hit_count,
54962306a36Sopenharmony_ci			  multixri_pool->other_pbl_hit_count);
55062306a36Sopenharmony_ci		if (strlcat(buf, tmp, size) >= size)
55162306a36Sopenharmony_ci			break;
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci		scnprintf(tmp, sizeof(tmp),
55462306a36Sopenharmony_ci			  " | %4d %4d %5d",
55562306a36Sopenharmony_ci			  multixri_pool->stat_pbl_count,
55662306a36Sopenharmony_ci			  multixri_pool->stat_pvt_count,
55762306a36Sopenharmony_ci			  multixri_pool->stat_busy_count);
55862306a36Sopenharmony_ci		if (strlcat(buf, tmp, size) >= size)
55962306a36Sopenharmony_ci			break;
56062306a36Sopenharmony_ci#endif
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci		scnprintf(tmp, sizeof(tmp), "\n");
56362306a36Sopenharmony_ci		if (strlcat(buf, tmp, size) >= size)
56462306a36Sopenharmony_ci			break;
56562306a36Sopenharmony_ci	}
56662306a36Sopenharmony_ci	return strnlen(buf, size);
56762306a36Sopenharmony_ci}
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci#ifdef LPFC_HDWQ_LOCK_STAT
57162306a36Sopenharmony_cistatic int lpfc_debugfs_last_lock;
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci/**
57462306a36Sopenharmony_ci * lpfc_debugfs_lockstat_data - Dump Hardware Queue info to a buffer
57562306a36Sopenharmony_ci * @phba: The HBA to gather host buffer info from.
57662306a36Sopenharmony_ci * @buf: The buffer to dump log into.
57762306a36Sopenharmony_ci * @size: The maximum amount of data to process.
57862306a36Sopenharmony_ci *
57962306a36Sopenharmony_ci * Description:
58062306a36Sopenharmony_ci * This routine dumps the Hardware Queue info from the @phba to @buf up to
58162306a36Sopenharmony_ci * @size number of bytes. A header that describes the current hdwq state will be
58262306a36Sopenharmony_ci * dumped to @buf first and then info on each hdwq entry will be dumped to @buf
58362306a36Sopenharmony_ci * until @size bytes have been dumped or all the hdwq info has been dumped.
58462306a36Sopenharmony_ci *
58562306a36Sopenharmony_ci * Notes:
58662306a36Sopenharmony_ci * This routine will rotate through each configured Hardware Queue each
58762306a36Sopenharmony_ci * time called.
58862306a36Sopenharmony_ci *
58962306a36Sopenharmony_ci * Return Value:
59062306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will
59162306a36Sopenharmony_ci * not exceed @size.
59262306a36Sopenharmony_ci **/
59362306a36Sopenharmony_cistatic int
59462306a36Sopenharmony_cilpfc_debugfs_lockstat_data(struct lpfc_hba *phba, char *buf, int size)
59562306a36Sopenharmony_ci{
59662306a36Sopenharmony_ci	struct lpfc_sli4_hdw_queue *qp;
59762306a36Sopenharmony_ci	int len = 0;
59862306a36Sopenharmony_ci	int i;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	if (phba->sli_rev != LPFC_SLI_REV4)
60162306a36Sopenharmony_ci		return 0;
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci	if (!phba->sli4_hba.hdwq)
60462306a36Sopenharmony_ci		return 0;
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	for (i = 0; i < phba->cfg_hdw_queue; i++) {
60762306a36Sopenharmony_ci		if (len > (LPFC_HDWQINFO_SIZE - 100))
60862306a36Sopenharmony_ci			break;
60962306a36Sopenharmony_ci		qp = &phba->sli4_hba.hdwq[lpfc_debugfs_last_lock];
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len, "HdwQ %03d Lock ", i);
61262306a36Sopenharmony_ci		if (phba->cfg_xri_rebalancing) {
61362306a36Sopenharmony_ci			len += scnprintf(buf + len, size - len,
61462306a36Sopenharmony_ci					 "get_pvt:%d mv_pvt:%d "
61562306a36Sopenharmony_ci					 "mv2pub:%d mv2pvt:%d "
61662306a36Sopenharmony_ci					 "put_pvt:%d put_pub:%d wq:%d\n",
61762306a36Sopenharmony_ci					 qp->lock_conflict.alloc_pvt_pool,
61862306a36Sopenharmony_ci					 qp->lock_conflict.mv_from_pvt_pool,
61962306a36Sopenharmony_ci					 qp->lock_conflict.mv_to_pub_pool,
62062306a36Sopenharmony_ci					 qp->lock_conflict.mv_to_pvt_pool,
62162306a36Sopenharmony_ci					 qp->lock_conflict.free_pvt_pool,
62262306a36Sopenharmony_ci					 qp->lock_conflict.free_pub_pool,
62362306a36Sopenharmony_ci					 qp->lock_conflict.wq_access);
62462306a36Sopenharmony_ci		} else {
62562306a36Sopenharmony_ci			len += scnprintf(buf + len, size - len,
62662306a36Sopenharmony_ci					 "get:%d put:%d free:%d wq:%d\n",
62762306a36Sopenharmony_ci					 qp->lock_conflict.alloc_xri_get,
62862306a36Sopenharmony_ci					 qp->lock_conflict.alloc_xri_put,
62962306a36Sopenharmony_ci					 qp->lock_conflict.free_xri,
63062306a36Sopenharmony_ci					 qp->lock_conflict.wq_access);
63162306a36Sopenharmony_ci		}
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci		lpfc_debugfs_last_lock++;
63462306a36Sopenharmony_ci		if (lpfc_debugfs_last_lock >= phba->cfg_hdw_queue)
63562306a36Sopenharmony_ci			lpfc_debugfs_last_lock = 0;
63662306a36Sopenharmony_ci	}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci	return len;
63962306a36Sopenharmony_ci}
64062306a36Sopenharmony_ci#endif
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_cistatic int lpfc_debugfs_last_hba_slim_off;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci/**
64562306a36Sopenharmony_ci * lpfc_debugfs_dumpHBASlim_data - Dump HBA SLIM info to a buffer
64662306a36Sopenharmony_ci * @phba: The HBA to gather SLIM info from.
64762306a36Sopenharmony_ci * @buf: The buffer to dump log into.
64862306a36Sopenharmony_ci * @size: The maximum amount of data to process.
64962306a36Sopenharmony_ci *
65062306a36Sopenharmony_ci * Description:
65162306a36Sopenharmony_ci * This routine dumps the current contents of HBA SLIM for the HBA associated
65262306a36Sopenharmony_ci * with @phba to @buf up to @size bytes of data. This is the raw HBA SLIM data.
65362306a36Sopenharmony_ci *
65462306a36Sopenharmony_ci * Notes:
65562306a36Sopenharmony_ci * This routine will only dump up to 1024 bytes of data each time called and
65662306a36Sopenharmony_ci * should be called multiple times to dump the entire HBA SLIM.
65762306a36Sopenharmony_ci *
65862306a36Sopenharmony_ci * Return Value:
65962306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will
66062306a36Sopenharmony_ci * not exceed @size.
66162306a36Sopenharmony_ci **/
66262306a36Sopenharmony_cistatic int
66362306a36Sopenharmony_cilpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
66462306a36Sopenharmony_ci{
66562306a36Sopenharmony_ci	int len = 0;
66662306a36Sopenharmony_ci	int i, off;
66762306a36Sopenharmony_ci	uint32_t *ptr;
66862306a36Sopenharmony_ci	char *buffer;
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	buffer = kmalloc(1024, GFP_KERNEL);
67162306a36Sopenharmony_ci	if (!buffer)
67262306a36Sopenharmony_ci		return 0;
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	off = 0;
67562306a36Sopenharmony_ci	spin_lock_irq(&phba->hbalock);
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	len +=  scnprintf(buf+len, size-len, "HBA SLIM\n");
67862306a36Sopenharmony_ci	lpfc_memcpy_from_slim(buffer,
67962306a36Sopenharmony_ci		phba->MBslimaddr + lpfc_debugfs_last_hba_slim_off, 1024);
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	ptr = (uint32_t *)&buffer[0];
68262306a36Sopenharmony_ci	off = lpfc_debugfs_last_hba_slim_off;
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	/* Set it up for the next time */
68562306a36Sopenharmony_ci	lpfc_debugfs_last_hba_slim_off += 1024;
68662306a36Sopenharmony_ci	if (lpfc_debugfs_last_hba_slim_off >= 4096)
68762306a36Sopenharmony_ci		lpfc_debugfs_last_hba_slim_off = 0;
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	i = 1024;
69062306a36Sopenharmony_ci	while (i > 0) {
69162306a36Sopenharmony_ci		len +=  scnprintf(buf+len, size-len,
69262306a36Sopenharmony_ci		"%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
69362306a36Sopenharmony_ci		off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4),
69462306a36Sopenharmony_ci		*(ptr+5), *(ptr+6), *(ptr+7));
69562306a36Sopenharmony_ci		ptr += 8;
69662306a36Sopenharmony_ci		i -= (8 * sizeof(uint32_t));
69762306a36Sopenharmony_ci		off += (8 * sizeof(uint32_t));
69862306a36Sopenharmony_ci	}
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	spin_unlock_irq(&phba->hbalock);
70162306a36Sopenharmony_ci	kfree(buffer);
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	return len;
70462306a36Sopenharmony_ci}
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci/**
70762306a36Sopenharmony_ci * lpfc_debugfs_dumpHostSlim_data - Dump host SLIM info to a buffer
70862306a36Sopenharmony_ci * @phba: The HBA to gather Host SLIM info from.
70962306a36Sopenharmony_ci * @buf: The buffer to dump log into.
71062306a36Sopenharmony_ci * @size: The maximum amount of data to process.
71162306a36Sopenharmony_ci *
71262306a36Sopenharmony_ci * Description:
71362306a36Sopenharmony_ci * This routine dumps the current contents of host SLIM for the host associated
71462306a36Sopenharmony_ci * with @phba to @buf up to @size bytes of data. The dump will contain the
71562306a36Sopenharmony_ci * Mailbox, PCB, Rings, and Registers that are located in host memory.
71662306a36Sopenharmony_ci *
71762306a36Sopenharmony_ci * Return Value:
71862306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will
71962306a36Sopenharmony_ci * not exceed @size.
72062306a36Sopenharmony_ci **/
72162306a36Sopenharmony_cistatic int
72262306a36Sopenharmony_cilpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size)
72362306a36Sopenharmony_ci{
72462306a36Sopenharmony_ci	int len = 0;
72562306a36Sopenharmony_ci	int i, off;
72662306a36Sopenharmony_ci	uint32_t word0, word1, word2, word3;
72762306a36Sopenharmony_ci	uint32_t *ptr;
72862306a36Sopenharmony_ci	struct lpfc_pgp *pgpp;
72962306a36Sopenharmony_ci	struct lpfc_sli *psli = &phba->sli;
73062306a36Sopenharmony_ci	struct lpfc_sli_ring *pring;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	off = 0;
73362306a36Sopenharmony_ci	spin_lock_irq(&phba->hbalock);
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	len +=  scnprintf(buf+len, size-len, "SLIM Mailbox\n");
73662306a36Sopenharmony_ci	ptr = (uint32_t *)phba->slim2p.virt;
73762306a36Sopenharmony_ci	i = sizeof(MAILBOX_t);
73862306a36Sopenharmony_ci	while (i > 0) {
73962306a36Sopenharmony_ci		len +=  scnprintf(buf+len, size-len,
74062306a36Sopenharmony_ci		"%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
74162306a36Sopenharmony_ci		off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4),
74262306a36Sopenharmony_ci		*(ptr+5), *(ptr+6), *(ptr+7));
74362306a36Sopenharmony_ci		ptr += 8;
74462306a36Sopenharmony_ci		i -= (8 * sizeof(uint32_t));
74562306a36Sopenharmony_ci		off += (8 * sizeof(uint32_t));
74662306a36Sopenharmony_ci	}
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci	len +=  scnprintf(buf+len, size-len, "SLIM PCB\n");
74962306a36Sopenharmony_ci	ptr = (uint32_t *)phba->pcb;
75062306a36Sopenharmony_ci	i = sizeof(PCB_t);
75162306a36Sopenharmony_ci	while (i > 0) {
75262306a36Sopenharmony_ci		len +=  scnprintf(buf+len, size-len,
75362306a36Sopenharmony_ci		"%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
75462306a36Sopenharmony_ci		off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4),
75562306a36Sopenharmony_ci		*(ptr+5), *(ptr+6), *(ptr+7));
75662306a36Sopenharmony_ci		ptr += 8;
75762306a36Sopenharmony_ci		i -= (8 * sizeof(uint32_t));
75862306a36Sopenharmony_ci		off += (8 * sizeof(uint32_t));
75962306a36Sopenharmony_ci	}
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci	if (phba->sli_rev <= LPFC_SLI_REV3) {
76262306a36Sopenharmony_ci		for (i = 0; i < 4; i++) {
76362306a36Sopenharmony_ci			pgpp = &phba->port_gp[i];
76462306a36Sopenharmony_ci			pring = &psli->sli3_ring[i];
76562306a36Sopenharmony_ci			len +=  scnprintf(buf+len, size-len,
76662306a36Sopenharmony_ci					 "Ring %d: CMD GetInx:%d "
76762306a36Sopenharmony_ci					 "(Max:%d Next:%d "
76862306a36Sopenharmony_ci					 "Local:%d flg:x%x)  "
76962306a36Sopenharmony_ci					 "RSP PutInx:%d Max:%d\n",
77062306a36Sopenharmony_ci					 i, pgpp->cmdGetInx,
77162306a36Sopenharmony_ci					 pring->sli.sli3.numCiocb,
77262306a36Sopenharmony_ci					 pring->sli.sli3.next_cmdidx,
77362306a36Sopenharmony_ci					 pring->sli.sli3.local_getidx,
77462306a36Sopenharmony_ci					 pring->flag, pgpp->rspPutInx,
77562306a36Sopenharmony_ci					 pring->sli.sli3.numRiocb);
77662306a36Sopenharmony_ci		}
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci		word0 = readl(phba->HAregaddr);
77962306a36Sopenharmony_ci		word1 = readl(phba->CAregaddr);
78062306a36Sopenharmony_ci		word2 = readl(phba->HSregaddr);
78162306a36Sopenharmony_ci		word3 = readl(phba->HCregaddr);
78262306a36Sopenharmony_ci		len +=  scnprintf(buf+len, size-len, "HA:%08x CA:%08x HS:%08x "
78362306a36Sopenharmony_ci				 "HC:%08x\n", word0, word1, word2, word3);
78462306a36Sopenharmony_ci	}
78562306a36Sopenharmony_ci	spin_unlock_irq(&phba->hbalock);
78662306a36Sopenharmony_ci	return len;
78762306a36Sopenharmony_ci}
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci/**
79062306a36Sopenharmony_ci * lpfc_debugfs_nodelist_data - Dump target node list to a buffer
79162306a36Sopenharmony_ci * @vport: The vport to gather target node info from.
79262306a36Sopenharmony_ci * @buf: The buffer to dump log into.
79362306a36Sopenharmony_ci * @size: The maximum amount of data to process.
79462306a36Sopenharmony_ci *
79562306a36Sopenharmony_ci * Description:
79662306a36Sopenharmony_ci * This routine dumps the current target node list associated with @vport to
79762306a36Sopenharmony_ci * @buf up to @size bytes of data. Each node entry in the dump will contain a
79862306a36Sopenharmony_ci * node state, DID, WWPN, WWNN, RPI, flags, type, and other useful fields.
79962306a36Sopenharmony_ci *
80062306a36Sopenharmony_ci * Return Value:
80162306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will
80262306a36Sopenharmony_ci * not exceed @size.
80362306a36Sopenharmony_ci **/
80462306a36Sopenharmony_cistatic int
80562306a36Sopenharmony_cilpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
80662306a36Sopenharmony_ci{
80762306a36Sopenharmony_ci	int len = 0;
80862306a36Sopenharmony_ci	int i, iocnt, outio, cnt;
80962306a36Sopenharmony_ci	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
81062306a36Sopenharmony_ci	struct lpfc_hba  *phba = vport->phba;
81162306a36Sopenharmony_ci	struct lpfc_nodelist *ndlp;
81262306a36Sopenharmony_ci	unsigned char *statep;
81362306a36Sopenharmony_ci	struct nvme_fc_local_port *localport;
81462306a36Sopenharmony_ci	struct nvme_fc_remote_port *nrport = NULL;
81562306a36Sopenharmony_ci	struct lpfc_nvme_rport *rport;
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
81862306a36Sopenharmony_ci	outio = 0;
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci	len += scnprintf(buf+len, size-len, "\nFCP Nodelist Entries ...\n");
82162306a36Sopenharmony_ci	spin_lock_irq(shost->host_lock);
82262306a36Sopenharmony_ci	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
82362306a36Sopenharmony_ci		iocnt = 0;
82462306a36Sopenharmony_ci		if (!cnt) {
82562306a36Sopenharmony_ci			len +=  scnprintf(buf+len, size-len,
82662306a36Sopenharmony_ci				"Missing Nodelist Entries\n");
82762306a36Sopenharmony_ci			break;
82862306a36Sopenharmony_ci		}
82962306a36Sopenharmony_ci		cnt--;
83062306a36Sopenharmony_ci		switch (ndlp->nlp_state) {
83162306a36Sopenharmony_ci		case NLP_STE_UNUSED_NODE:
83262306a36Sopenharmony_ci			statep = "UNUSED";
83362306a36Sopenharmony_ci			break;
83462306a36Sopenharmony_ci		case NLP_STE_PLOGI_ISSUE:
83562306a36Sopenharmony_ci			statep = "PLOGI ";
83662306a36Sopenharmony_ci			break;
83762306a36Sopenharmony_ci		case NLP_STE_ADISC_ISSUE:
83862306a36Sopenharmony_ci			statep = "ADISC ";
83962306a36Sopenharmony_ci			break;
84062306a36Sopenharmony_ci		case NLP_STE_REG_LOGIN_ISSUE:
84162306a36Sopenharmony_ci			statep = "REGLOG";
84262306a36Sopenharmony_ci			break;
84362306a36Sopenharmony_ci		case NLP_STE_PRLI_ISSUE:
84462306a36Sopenharmony_ci			statep = "PRLI  ";
84562306a36Sopenharmony_ci			break;
84662306a36Sopenharmony_ci		case NLP_STE_LOGO_ISSUE:
84762306a36Sopenharmony_ci			statep = "LOGO  ";
84862306a36Sopenharmony_ci			break;
84962306a36Sopenharmony_ci		case NLP_STE_UNMAPPED_NODE:
85062306a36Sopenharmony_ci			statep = "UNMAP ";
85162306a36Sopenharmony_ci			iocnt = 1;
85262306a36Sopenharmony_ci			break;
85362306a36Sopenharmony_ci		case NLP_STE_MAPPED_NODE:
85462306a36Sopenharmony_ci			statep = "MAPPED";
85562306a36Sopenharmony_ci			iocnt = 1;
85662306a36Sopenharmony_ci			break;
85762306a36Sopenharmony_ci		case NLP_STE_NPR_NODE:
85862306a36Sopenharmony_ci			statep = "NPR   ";
85962306a36Sopenharmony_ci			break;
86062306a36Sopenharmony_ci		default:
86162306a36Sopenharmony_ci			statep = "UNKNOWN";
86262306a36Sopenharmony_ci		}
86362306a36Sopenharmony_ci		len += scnprintf(buf+len, size-len, "%s DID:x%06x ",
86462306a36Sopenharmony_ci				statep, ndlp->nlp_DID);
86562306a36Sopenharmony_ci		len += scnprintf(buf+len, size-len,
86662306a36Sopenharmony_ci				"WWPN x%016llx ",
86762306a36Sopenharmony_ci				wwn_to_u64(ndlp->nlp_portname.u.wwn));
86862306a36Sopenharmony_ci		len += scnprintf(buf+len, size-len,
86962306a36Sopenharmony_ci				"WWNN x%016llx ",
87062306a36Sopenharmony_ci				wwn_to_u64(ndlp->nlp_nodename.u.wwn));
87162306a36Sopenharmony_ci		len += scnprintf(buf+len, size-len, "RPI:x%04x ",
87262306a36Sopenharmony_ci				 ndlp->nlp_rpi);
87362306a36Sopenharmony_ci		len +=  scnprintf(buf+len, size-len, "flag:x%08x ",
87462306a36Sopenharmony_ci			ndlp->nlp_flag);
87562306a36Sopenharmony_ci		if (!ndlp->nlp_type)
87662306a36Sopenharmony_ci			len += scnprintf(buf+len, size-len, "UNKNOWN_TYPE ");
87762306a36Sopenharmony_ci		if (ndlp->nlp_type & NLP_FC_NODE)
87862306a36Sopenharmony_ci			len += scnprintf(buf+len, size-len, "FC_NODE ");
87962306a36Sopenharmony_ci		if (ndlp->nlp_type & NLP_FABRIC) {
88062306a36Sopenharmony_ci			len += scnprintf(buf+len, size-len, "FABRIC ");
88162306a36Sopenharmony_ci			iocnt = 0;
88262306a36Sopenharmony_ci		}
88362306a36Sopenharmony_ci		if (ndlp->nlp_type & NLP_FCP_TARGET)
88462306a36Sopenharmony_ci			len += scnprintf(buf+len, size-len, "FCP_TGT sid:%d ",
88562306a36Sopenharmony_ci				ndlp->nlp_sid);
88662306a36Sopenharmony_ci		if (ndlp->nlp_type & NLP_FCP_INITIATOR)
88762306a36Sopenharmony_ci			len += scnprintf(buf+len, size-len, "FCP_INITIATOR ");
88862306a36Sopenharmony_ci		if (ndlp->nlp_type & NLP_NVME_TARGET)
88962306a36Sopenharmony_ci			len += scnprintf(buf + len,
89062306a36Sopenharmony_ci					size - len, "NVME_TGT sid:%d ",
89162306a36Sopenharmony_ci					NLP_NO_SID);
89262306a36Sopenharmony_ci		if (ndlp->nlp_type & NLP_NVME_INITIATOR)
89362306a36Sopenharmony_ci			len += scnprintf(buf + len,
89462306a36Sopenharmony_ci					size - len, "NVME_INITIATOR ");
89562306a36Sopenharmony_ci		len += scnprintf(buf+len, size-len, "refcnt:%d",
89662306a36Sopenharmony_ci			kref_read(&ndlp->kref));
89762306a36Sopenharmony_ci		if (iocnt) {
89862306a36Sopenharmony_ci			i = atomic_read(&ndlp->cmd_pending);
89962306a36Sopenharmony_ci			len += scnprintf(buf + len, size - len,
90062306a36Sopenharmony_ci					" OutIO:x%x Qdepth x%x",
90162306a36Sopenharmony_ci					i, ndlp->cmd_qdepth);
90262306a36Sopenharmony_ci			outio += i;
90362306a36Sopenharmony_ci		}
90462306a36Sopenharmony_ci		len += scnprintf(buf+len, size-len, " xpt:x%x",
90562306a36Sopenharmony_ci				 ndlp->fc4_xpt_flags);
90662306a36Sopenharmony_ci		if (ndlp->nlp_defer_did != NLP_EVT_NOTHING_PENDING)
90762306a36Sopenharmony_ci			len += scnprintf(buf+len, size-len, " defer:%x",
90862306a36Sopenharmony_ci					 ndlp->nlp_defer_did);
90962306a36Sopenharmony_ci		len +=  scnprintf(buf+len, size-len, "\n");
91062306a36Sopenharmony_ci	}
91162306a36Sopenharmony_ci	spin_unlock_irq(shost->host_lock);
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	len += scnprintf(buf + len, size - len,
91462306a36Sopenharmony_ci			"\nOutstanding IO x%x\n",  outio);
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	if (phba->nvmet_support && phba->targetport && (vport == phba->pport)) {
91762306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
91862306a36Sopenharmony_ci				"\nNVME Targetport Entry ...\n");
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci		/* Port state is only one of two values for now. */
92162306a36Sopenharmony_ci		if (phba->targetport->port_id)
92262306a36Sopenharmony_ci			statep = "REGISTERED";
92362306a36Sopenharmony_ci		else
92462306a36Sopenharmony_ci			statep = "INIT";
92562306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
92662306a36Sopenharmony_ci				"TGT WWNN x%llx WWPN x%llx State %s\n",
92762306a36Sopenharmony_ci				wwn_to_u64(vport->fc_nodename.u.wwn),
92862306a36Sopenharmony_ci				wwn_to_u64(vport->fc_portname.u.wwn),
92962306a36Sopenharmony_ci				statep);
93062306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
93162306a36Sopenharmony_ci				"    Targetport DID x%06x\n",
93262306a36Sopenharmony_ci				phba->targetport->port_id);
93362306a36Sopenharmony_ci		goto out_exit;
93462306a36Sopenharmony_ci	}
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci	len += scnprintf(buf + len, size - len,
93762306a36Sopenharmony_ci				"\nNVME Lport/Rport Entries ...\n");
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci	localport = vport->localport;
94062306a36Sopenharmony_ci	if (!localport)
94162306a36Sopenharmony_ci		goto out_exit;
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci	spin_lock_irq(shost->host_lock);
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci	/* Port state is only one of two values for now. */
94662306a36Sopenharmony_ci	if (localport->port_id)
94762306a36Sopenharmony_ci		statep = "ONLINE";
94862306a36Sopenharmony_ci	else
94962306a36Sopenharmony_ci		statep = "UNKNOWN ";
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ci	len += scnprintf(buf + len, size - len,
95262306a36Sopenharmony_ci			"Lport DID x%06x PortState %s\n",
95362306a36Sopenharmony_ci			localport->port_id, statep);
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_ci	len += scnprintf(buf + len, size - len, "\tRport List:\n");
95662306a36Sopenharmony_ci	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
95762306a36Sopenharmony_ci		/* local short-hand pointer. */
95862306a36Sopenharmony_ci		spin_lock(&ndlp->lock);
95962306a36Sopenharmony_ci		rport = lpfc_ndlp_get_nrport(ndlp);
96062306a36Sopenharmony_ci		if (rport)
96162306a36Sopenharmony_ci			nrport = rport->remoteport;
96262306a36Sopenharmony_ci		else
96362306a36Sopenharmony_ci			nrport = NULL;
96462306a36Sopenharmony_ci		spin_unlock(&ndlp->lock);
96562306a36Sopenharmony_ci		if (!nrport)
96662306a36Sopenharmony_ci			continue;
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci		/* Port state is only one of two values for now. */
96962306a36Sopenharmony_ci		switch (nrport->port_state) {
97062306a36Sopenharmony_ci		case FC_OBJSTATE_ONLINE:
97162306a36Sopenharmony_ci			statep = "ONLINE";
97262306a36Sopenharmony_ci			break;
97362306a36Sopenharmony_ci		case FC_OBJSTATE_UNKNOWN:
97462306a36Sopenharmony_ci			statep = "UNKNOWN ";
97562306a36Sopenharmony_ci			break;
97662306a36Sopenharmony_ci		default:
97762306a36Sopenharmony_ci			statep = "UNSUPPORTED";
97862306a36Sopenharmony_ci			break;
97962306a36Sopenharmony_ci		}
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci		/* Tab in to show lport ownership. */
98262306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
98362306a36Sopenharmony_ci				"\t%s Port ID:x%06x ",
98462306a36Sopenharmony_ci				statep, nrport->port_id);
98562306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len, "WWPN x%llx ",
98662306a36Sopenharmony_ci				nrport->port_name);
98762306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len, "WWNN x%llx ",
98862306a36Sopenharmony_ci				nrport->node_name);
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci		/* An NVME rport can have multiple roles. */
99162306a36Sopenharmony_ci		if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR)
99262306a36Sopenharmony_ci			len +=  scnprintf(buf + len, size - len,
99362306a36Sopenharmony_ci					 "INITIATOR ");
99462306a36Sopenharmony_ci		if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET)
99562306a36Sopenharmony_ci			len +=  scnprintf(buf + len, size - len,
99662306a36Sopenharmony_ci					 "TARGET ");
99762306a36Sopenharmony_ci		if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY)
99862306a36Sopenharmony_ci			len +=  scnprintf(buf + len, size - len,
99962306a36Sopenharmony_ci					 "DISCSRVC ");
100062306a36Sopenharmony_ci		if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR |
100162306a36Sopenharmony_ci					  FC_PORT_ROLE_NVME_TARGET |
100262306a36Sopenharmony_ci					  FC_PORT_ROLE_NVME_DISCOVERY))
100362306a36Sopenharmony_ci			len +=  scnprintf(buf + len, size - len,
100462306a36Sopenharmony_ci					 "UNKNOWN ROLE x%x",
100562306a36Sopenharmony_ci					 nrport->port_role);
100662306a36Sopenharmony_ci		/* Terminate the string. */
100762306a36Sopenharmony_ci		len +=  scnprintf(buf + len, size - len, "\n");
100862306a36Sopenharmony_ci	}
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	spin_unlock_irq(shost->host_lock);
101162306a36Sopenharmony_ci out_exit:
101262306a36Sopenharmony_ci	return len;
101362306a36Sopenharmony_ci}
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci/**
101662306a36Sopenharmony_ci * lpfc_debugfs_nvmestat_data - Dump target node list to a buffer
101762306a36Sopenharmony_ci * @vport: The vport to gather target node info from.
101862306a36Sopenharmony_ci * @buf: The buffer to dump log into.
101962306a36Sopenharmony_ci * @size: The maximum amount of data to process.
102062306a36Sopenharmony_ci *
102162306a36Sopenharmony_ci * Description:
102262306a36Sopenharmony_ci * This routine dumps the NVME statistics associated with @vport
102362306a36Sopenharmony_ci *
102462306a36Sopenharmony_ci * Return Value:
102562306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will
102662306a36Sopenharmony_ci * not exceed @size.
102762306a36Sopenharmony_ci **/
102862306a36Sopenharmony_cistatic int
102962306a36Sopenharmony_cilpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size)
103062306a36Sopenharmony_ci{
103162306a36Sopenharmony_ci	struct lpfc_hba   *phba = vport->phba;
103262306a36Sopenharmony_ci	struct lpfc_nvmet_tgtport *tgtp;
103362306a36Sopenharmony_ci	struct lpfc_async_xchg_ctx *ctxp, *next_ctxp;
103462306a36Sopenharmony_ci	struct nvme_fc_local_port *localport;
103562306a36Sopenharmony_ci	struct lpfc_fc4_ctrl_stat *cstat;
103662306a36Sopenharmony_ci	struct lpfc_nvme_lport *lport;
103762306a36Sopenharmony_ci	uint64_t data1, data2, data3;
103862306a36Sopenharmony_ci	uint64_t tot, totin, totout;
103962306a36Sopenharmony_ci	int cnt, i;
104062306a36Sopenharmony_ci	int len = 0;
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	if (phba->nvmet_support) {
104362306a36Sopenharmony_ci		if (!phba->targetport)
104462306a36Sopenharmony_ci			return len;
104562306a36Sopenharmony_ci		tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
104662306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
104762306a36Sopenharmony_ci				"\nNVME Targetport Statistics\n");
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
105062306a36Sopenharmony_ci				"LS: Rcv %08x Drop %08x Abort %08x\n",
105162306a36Sopenharmony_ci				atomic_read(&tgtp->rcv_ls_req_in),
105262306a36Sopenharmony_ci				atomic_read(&tgtp->rcv_ls_req_drop),
105362306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_ls_abort));
105462306a36Sopenharmony_ci		if (atomic_read(&tgtp->rcv_ls_req_in) !=
105562306a36Sopenharmony_ci		    atomic_read(&tgtp->rcv_ls_req_out)) {
105662306a36Sopenharmony_ci			len += scnprintf(buf + len, size - len,
105762306a36Sopenharmony_ci					"Rcv LS: in %08x != out %08x\n",
105862306a36Sopenharmony_ci					atomic_read(&tgtp->rcv_ls_req_in),
105962306a36Sopenharmony_ci					atomic_read(&tgtp->rcv_ls_req_out));
106062306a36Sopenharmony_ci		}
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
106362306a36Sopenharmony_ci				"LS: Xmt %08x Drop %08x Cmpl %08x\n",
106462306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_ls_rsp),
106562306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_ls_drop),
106662306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_ls_rsp_cmpl));
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
106962306a36Sopenharmony_ci				"LS: RSP Abort %08x xb %08x Err %08x\n",
107062306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_ls_rsp_aborted),
107162306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_ls_rsp_xb_set),
107262306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_ls_rsp_error));
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
107562306a36Sopenharmony_ci				"FCP: Rcv %08x Defer %08x Release %08x "
107662306a36Sopenharmony_ci				"Drop %08x\n",
107762306a36Sopenharmony_ci				atomic_read(&tgtp->rcv_fcp_cmd_in),
107862306a36Sopenharmony_ci				atomic_read(&tgtp->rcv_fcp_cmd_defer),
107962306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_fcp_release),
108062306a36Sopenharmony_ci				atomic_read(&tgtp->rcv_fcp_cmd_drop));
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci		if (atomic_read(&tgtp->rcv_fcp_cmd_in) !=
108362306a36Sopenharmony_ci		    atomic_read(&tgtp->rcv_fcp_cmd_out)) {
108462306a36Sopenharmony_ci			len += scnprintf(buf + len, size - len,
108562306a36Sopenharmony_ci					"Rcv FCP: in %08x != out %08x\n",
108662306a36Sopenharmony_ci					atomic_read(&tgtp->rcv_fcp_cmd_in),
108762306a36Sopenharmony_ci					atomic_read(&tgtp->rcv_fcp_cmd_out));
108862306a36Sopenharmony_ci		}
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
109162306a36Sopenharmony_ci				"FCP Rsp: read %08x readrsp %08x "
109262306a36Sopenharmony_ci				"write %08x rsp %08x\n",
109362306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_fcp_read),
109462306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_fcp_read_rsp),
109562306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_fcp_write),
109662306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_fcp_rsp));
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
109962306a36Sopenharmony_ci				"FCP Rsp Cmpl: %08x err %08x drop %08x\n",
110062306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_fcp_rsp_cmpl),
110162306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_fcp_rsp_error),
110262306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_fcp_rsp_drop));
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
110562306a36Sopenharmony_ci				"FCP Rsp Abort: %08x xb %08x xricqe  %08x\n",
110662306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_fcp_rsp_aborted),
110762306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_fcp_rsp_xb_set),
110862306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_fcp_xri_abort_cqe));
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
111162306a36Sopenharmony_ci				"ABORT: Xmt %08x Cmpl %08x\n",
111262306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_fcp_abort),
111362306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_fcp_abort_cmpl));
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
111662306a36Sopenharmony_ci				"ABORT: Sol %08x  Usol %08x Err %08x Cmpl %08x",
111762306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_abort_sol),
111862306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_abort_unsol),
111962306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_abort_rsp),
112062306a36Sopenharmony_ci				atomic_read(&tgtp->xmt_abort_rsp_error));
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci		len +=  scnprintf(buf + len, size - len, "\n");
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci		cnt = 0;
112562306a36Sopenharmony_ci		spin_lock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
112662306a36Sopenharmony_ci		list_for_each_entry_safe(ctxp, next_ctxp,
112762306a36Sopenharmony_ci				&phba->sli4_hba.lpfc_abts_nvmet_ctx_list,
112862306a36Sopenharmony_ci				list) {
112962306a36Sopenharmony_ci			cnt++;
113062306a36Sopenharmony_ci		}
113162306a36Sopenharmony_ci		spin_unlock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
113262306a36Sopenharmony_ci		if (cnt) {
113362306a36Sopenharmony_ci			len += scnprintf(buf + len, size - len,
113462306a36Sopenharmony_ci					"ABORT: %d ctx entries\n", cnt);
113562306a36Sopenharmony_ci			spin_lock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
113662306a36Sopenharmony_ci			list_for_each_entry_safe(ctxp, next_ctxp,
113762306a36Sopenharmony_ci				    &phba->sli4_hba.lpfc_abts_nvmet_ctx_list,
113862306a36Sopenharmony_ci				    list) {
113962306a36Sopenharmony_ci				if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ))
114062306a36Sopenharmony_ci					break;
114162306a36Sopenharmony_ci				len += scnprintf(buf + len, size - len,
114262306a36Sopenharmony_ci						"Entry: oxid %x state %x "
114362306a36Sopenharmony_ci						"flag %x\n",
114462306a36Sopenharmony_ci						ctxp->oxid, ctxp->state,
114562306a36Sopenharmony_ci						ctxp->flag);
114662306a36Sopenharmony_ci			}
114762306a36Sopenharmony_ci			spin_unlock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
114862306a36Sopenharmony_ci		}
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci		/* Calculate outstanding IOs */
115162306a36Sopenharmony_ci		tot = atomic_read(&tgtp->rcv_fcp_cmd_drop);
115262306a36Sopenharmony_ci		tot += atomic_read(&tgtp->xmt_fcp_release);
115362306a36Sopenharmony_ci		tot = atomic_read(&tgtp->rcv_fcp_cmd_in) - tot;
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
115662306a36Sopenharmony_ci				"IO_CTX: %08x  WAIT: cur %08x tot %08x\n"
115762306a36Sopenharmony_ci				"CTX Outstanding %08llx\n",
115862306a36Sopenharmony_ci				phba->sli4_hba.nvmet_xri_cnt,
115962306a36Sopenharmony_ci				phba->sli4_hba.nvmet_io_wait_cnt,
116062306a36Sopenharmony_ci				phba->sli4_hba.nvmet_io_wait_total,
116162306a36Sopenharmony_ci				tot);
116262306a36Sopenharmony_ci	} else {
116362306a36Sopenharmony_ci		if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_NVME))
116462306a36Sopenharmony_ci			return len;
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci		localport = vport->localport;
116762306a36Sopenharmony_ci		if (!localport)
116862306a36Sopenharmony_ci			return len;
116962306a36Sopenharmony_ci		lport = (struct lpfc_nvme_lport *)localport->private;
117062306a36Sopenharmony_ci		if (!lport)
117162306a36Sopenharmony_ci			return len;
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
117462306a36Sopenharmony_ci				"\nNVME HDWQ Statistics\n");
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
117762306a36Sopenharmony_ci				"LS: Xmt %016x Cmpl %016x\n",
117862306a36Sopenharmony_ci				atomic_read(&lport->fc4NvmeLsRequests),
117962306a36Sopenharmony_ci				atomic_read(&lport->fc4NvmeLsCmpls));
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ci		totin = 0;
118262306a36Sopenharmony_ci		totout = 0;
118362306a36Sopenharmony_ci		for (i = 0; i < phba->cfg_hdw_queue; i++) {
118462306a36Sopenharmony_ci			cstat = &phba->sli4_hba.hdwq[i].nvme_cstat;
118562306a36Sopenharmony_ci			tot = cstat->io_cmpls;
118662306a36Sopenharmony_ci			totin += tot;
118762306a36Sopenharmony_ci			data1 = cstat->input_requests;
118862306a36Sopenharmony_ci			data2 = cstat->output_requests;
118962306a36Sopenharmony_ci			data3 = cstat->control_requests;
119062306a36Sopenharmony_ci			totout += (data1 + data2 + data3);
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci			/* Limit to 32, debugfs display buffer limitation */
119362306a36Sopenharmony_ci			if (i >= 32)
119462306a36Sopenharmony_ci				continue;
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci			len += scnprintf(buf + len, PAGE_SIZE - len,
119762306a36Sopenharmony_ci					"HDWQ (%d): Rd %016llx Wr %016llx "
119862306a36Sopenharmony_ci					"IO %016llx ",
119962306a36Sopenharmony_ci					i, data1, data2, data3);
120062306a36Sopenharmony_ci			len += scnprintf(buf + len, PAGE_SIZE - len,
120162306a36Sopenharmony_ci					"Cmpl %016llx OutIO %016llx\n",
120262306a36Sopenharmony_ci					tot, ((data1 + data2 + data3) - tot));
120362306a36Sopenharmony_ci		}
120462306a36Sopenharmony_ci		len += scnprintf(buf + len, PAGE_SIZE - len,
120562306a36Sopenharmony_ci				"Total FCP Cmpl %016llx Issue %016llx "
120662306a36Sopenharmony_ci				"OutIO %016llx\n",
120762306a36Sopenharmony_ci				totin, totout, totout - totin);
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
121062306a36Sopenharmony_ci				"LS Xmt Err: Abrt %08x Err %08x  "
121162306a36Sopenharmony_ci				"Cmpl Err: xb %08x Err %08x\n",
121262306a36Sopenharmony_ci				atomic_read(&lport->xmt_ls_abort),
121362306a36Sopenharmony_ci				atomic_read(&lport->xmt_ls_err),
121462306a36Sopenharmony_ci				atomic_read(&lport->cmpl_ls_xb),
121562306a36Sopenharmony_ci				atomic_read(&lport->cmpl_ls_err));
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
121862306a36Sopenharmony_ci				"FCP Xmt Err: noxri %06x nondlp %06x "
121962306a36Sopenharmony_ci				"qdepth %06x wqerr %06x err %06x Abrt %06x\n",
122062306a36Sopenharmony_ci				atomic_read(&lport->xmt_fcp_noxri),
122162306a36Sopenharmony_ci				atomic_read(&lport->xmt_fcp_bad_ndlp),
122262306a36Sopenharmony_ci				atomic_read(&lport->xmt_fcp_qdepth),
122362306a36Sopenharmony_ci				atomic_read(&lport->xmt_fcp_wqerr),
122462306a36Sopenharmony_ci				atomic_read(&lport->xmt_fcp_err),
122562306a36Sopenharmony_ci				atomic_read(&lport->xmt_fcp_abort));
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
122862306a36Sopenharmony_ci				"FCP Cmpl Err: xb %08x Err %08x\n",
122962306a36Sopenharmony_ci				atomic_read(&lport->cmpl_fcp_xb),
123062306a36Sopenharmony_ci				atomic_read(&lport->cmpl_fcp_err));
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	}
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci	return len;
123562306a36Sopenharmony_ci}
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci/**
123862306a36Sopenharmony_ci * lpfc_debugfs_scsistat_data - Dump target node list to a buffer
123962306a36Sopenharmony_ci * @vport: The vport to gather target node info from.
124062306a36Sopenharmony_ci * @buf: The buffer to dump log into.
124162306a36Sopenharmony_ci * @size: The maximum amount of data to process.
124262306a36Sopenharmony_ci *
124362306a36Sopenharmony_ci * Description:
124462306a36Sopenharmony_ci * This routine dumps the SCSI statistics associated with @vport
124562306a36Sopenharmony_ci *
124662306a36Sopenharmony_ci * Return Value:
124762306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will
124862306a36Sopenharmony_ci * not exceed @size.
124962306a36Sopenharmony_ci **/
125062306a36Sopenharmony_cistatic int
125162306a36Sopenharmony_cilpfc_debugfs_scsistat_data(struct lpfc_vport *vport, char *buf, int size)
125262306a36Sopenharmony_ci{
125362306a36Sopenharmony_ci	int len;
125462306a36Sopenharmony_ci	struct lpfc_hba *phba = vport->phba;
125562306a36Sopenharmony_ci	struct lpfc_fc4_ctrl_stat *cstat;
125662306a36Sopenharmony_ci	u64 data1, data2, data3;
125762306a36Sopenharmony_ci	u64 tot, totin, totout;
125862306a36Sopenharmony_ci	int i;
125962306a36Sopenharmony_ci	char tmp[LPFC_MAX_SCSI_INFO_TMP_LEN] = {0};
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_FCP) ||
126262306a36Sopenharmony_ci	    (phba->sli_rev != LPFC_SLI_REV4))
126362306a36Sopenharmony_ci		return 0;
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	scnprintf(buf, size, "SCSI HDWQ Statistics\n");
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci	totin = 0;
126862306a36Sopenharmony_ci	totout = 0;
126962306a36Sopenharmony_ci	for (i = 0; i < phba->cfg_hdw_queue; i++) {
127062306a36Sopenharmony_ci		cstat = &phba->sli4_hba.hdwq[i].scsi_cstat;
127162306a36Sopenharmony_ci		tot = cstat->io_cmpls;
127262306a36Sopenharmony_ci		totin += tot;
127362306a36Sopenharmony_ci		data1 = cstat->input_requests;
127462306a36Sopenharmony_ci		data2 = cstat->output_requests;
127562306a36Sopenharmony_ci		data3 = cstat->control_requests;
127662306a36Sopenharmony_ci		totout += (data1 + data2 + data3);
127762306a36Sopenharmony_ci
127862306a36Sopenharmony_ci		scnprintf(tmp, sizeof(tmp), "HDWQ (%d): Rd %016llx Wr %016llx "
127962306a36Sopenharmony_ci			  "IO %016llx ", i, data1, data2, data3);
128062306a36Sopenharmony_ci		if (strlcat(buf, tmp, size) >= size)
128162306a36Sopenharmony_ci			goto buffer_done;
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci		scnprintf(tmp, sizeof(tmp), "Cmpl %016llx OutIO %016llx\n",
128462306a36Sopenharmony_ci			  tot, ((data1 + data2 + data3) - tot));
128562306a36Sopenharmony_ci		if (strlcat(buf, tmp, size) >= size)
128662306a36Sopenharmony_ci			goto buffer_done;
128762306a36Sopenharmony_ci	}
128862306a36Sopenharmony_ci	scnprintf(tmp, sizeof(tmp), "Total FCP Cmpl %016llx Issue %016llx "
128962306a36Sopenharmony_ci		  "OutIO %016llx\n", totin, totout, totout - totin);
129062306a36Sopenharmony_ci	strlcat(buf, tmp, size);
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_cibuffer_done:
129362306a36Sopenharmony_ci	len = strnlen(buf, size);
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_ci	return len;
129662306a36Sopenharmony_ci}
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_civoid
129962306a36Sopenharmony_cilpfc_io_ktime(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
130062306a36Sopenharmony_ci{
130162306a36Sopenharmony_ci	uint64_t seg1, seg2, seg3, seg4;
130262306a36Sopenharmony_ci	uint64_t segsum;
130362306a36Sopenharmony_ci
130462306a36Sopenharmony_ci	if (!lpfc_cmd->ts_last_cmd ||
130562306a36Sopenharmony_ci	    !lpfc_cmd->ts_cmd_start ||
130662306a36Sopenharmony_ci	    !lpfc_cmd->ts_cmd_wqput ||
130762306a36Sopenharmony_ci	    !lpfc_cmd->ts_isr_cmpl ||
130862306a36Sopenharmony_ci	    !lpfc_cmd->ts_data_io)
130962306a36Sopenharmony_ci		return;
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci	if (lpfc_cmd->ts_data_io < lpfc_cmd->ts_cmd_start)
131262306a36Sopenharmony_ci		return;
131362306a36Sopenharmony_ci	if (lpfc_cmd->ts_cmd_start < lpfc_cmd->ts_last_cmd)
131462306a36Sopenharmony_ci		return;
131562306a36Sopenharmony_ci	if (lpfc_cmd->ts_cmd_wqput < lpfc_cmd->ts_cmd_start)
131662306a36Sopenharmony_ci		return;
131762306a36Sopenharmony_ci	if (lpfc_cmd->ts_isr_cmpl < lpfc_cmd->ts_cmd_wqput)
131862306a36Sopenharmony_ci		return;
131962306a36Sopenharmony_ci	if (lpfc_cmd->ts_data_io < lpfc_cmd->ts_isr_cmpl)
132062306a36Sopenharmony_ci		return;
132162306a36Sopenharmony_ci	/*
132262306a36Sopenharmony_ci	 * Segment 1 - Time from Last FCP command cmpl is handed
132362306a36Sopenharmony_ci	 * off to NVME Layer to start of next command.
132462306a36Sopenharmony_ci	 * Segment 2 - Time from Driver receives a IO cmd start
132562306a36Sopenharmony_ci	 * from NVME Layer to WQ put is done on IO cmd.
132662306a36Sopenharmony_ci	 * Segment 3 - Time from Driver WQ put is done on IO cmd
132762306a36Sopenharmony_ci	 * to MSI-X ISR for IO cmpl.
132862306a36Sopenharmony_ci	 * Segment 4 - Time from MSI-X ISR for IO cmpl to when
132962306a36Sopenharmony_ci	 * cmpl is handled off to the NVME Layer.
133062306a36Sopenharmony_ci	 */
133162306a36Sopenharmony_ci	seg1 = lpfc_cmd->ts_cmd_start - lpfc_cmd->ts_last_cmd;
133262306a36Sopenharmony_ci	if (seg1 > 5000000)  /* 5 ms - for sequential IOs only */
133362306a36Sopenharmony_ci		seg1 = 0;
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci	/* Calculate times relative to start of IO */
133662306a36Sopenharmony_ci	seg2 = (lpfc_cmd->ts_cmd_wqput - lpfc_cmd->ts_cmd_start);
133762306a36Sopenharmony_ci	segsum = seg2;
133862306a36Sopenharmony_ci	seg3 = lpfc_cmd->ts_isr_cmpl - lpfc_cmd->ts_cmd_start;
133962306a36Sopenharmony_ci	if (segsum > seg3)
134062306a36Sopenharmony_ci		return;
134162306a36Sopenharmony_ci	seg3 -= segsum;
134262306a36Sopenharmony_ci	segsum += seg3;
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_ci	seg4 = lpfc_cmd->ts_data_io - lpfc_cmd->ts_cmd_start;
134562306a36Sopenharmony_ci	if (segsum > seg4)
134662306a36Sopenharmony_ci		return;
134762306a36Sopenharmony_ci	seg4 -= segsum;
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_ci	phba->ktime_data_samples++;
135062306a36Sopenharmony_ci	phba->ktime_seg1_total += seg1;
135162306a36Sopenharmony_ci	if (seg1 < phba->ktime_seg1_min)
135262306a36Sopenharmony_ci		phba->ktime_seg1_min = seg1;
135362306a36Sopenharmony_ci	else if (seg1 > phba->ktime_seg1_max)
135462306a36Sopenharmony_ci		phba->ktime_seg1_max = seg1;
135562306a36Sopenharmony_ci	phba->ktime_seg2_total += seg2;
135662306a36Sopenharmony_ci	if (seg2 < phba->ktime_seg2_min)
135762306a36Sopenharmony_ci		phba->ktime_seg2_min = seg2;
135862306a36Sopenharmony_ci	else if (seg2 > phba->ktime_seg2_max)
135962306a36Sopenharmony_ci		phba->ktime_seg2_max = seg2;
136062306a36Sopenharmony_ci	phba->ktime_seg3_total += seg3;
136162306a36Sopenharmony_ci	if (seg3 < phba->ktime_seg3_min)
136262306a36Sopenharmony_ci		phba->ktime_seg3_min = seg3;
136362306a36Sopenharmony_ci	else if (seg3 > phba->ktime_seg3_max)
136462306a36Sopenharmony_ci		phba->ktime_seg3_max = seg3;
136562306a36Sopenharmony_ci	phba->ktime_seg4_total += seg4;
136662306a36Sopenharmony_ci	if (seg4 < phba->ktime_seg4_min)
136762306a36Sopenharmony_ci		phba->ktime_seg4_min = seg4;
136862306a36Sopenharmony_ci	else if (seg4 > phba->ktime_seg4_max)
136962306a36Sopenharmony_ci		phba->ktime_seg4_max = seg4;
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci	lpfc_cmd->ts_last_cmd = 0;
137262306a36Sopenharmony_ci	lpfc_cmd->ts_cmd_start = 0;
137362306a36Sopenharmony_ci	lpfc_cmd->ts_cmd_wqput  = 0;
137462306a36Sopenharmony_ci	lpfc_cmd->ts_isr_cmpl = 0;
137562306a36Sopenharmony_ci	lpfc_cmd->ts_data_io = 0;
137662306a36Sopenharmony_ci}
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci/**
137962306a36Sopenharmony_ci * lpfc_debugfs_ioktime_data - Dump target node list to a buffer
138062306a36Sopenharmony_ci * @vport: The vport to gather target node info from.
138162306a36Sopenharmony_ci * @buf: The buffer to dump log into.
138262306a36Sopenharmony_ci * @size: The maximum amount of data to process.
138362306a36Sopenharmony_ci *
138462306a36Sopenharmony_ci * Description:
138562306a36Sopenharmony_ci * This routine dumps the NVME statistics associated with @vport
138662306a36Sopenharmony_ci *
138762306a36Sopenharmony_ci * Return Value:
138862306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will
138962306a36Sopenharmony_ci * not exceed @size.
139062306a36Sopenharmony_ci **/
139162306a36Sopenharmony_cistatic int
139262306a36Sopenharmony_cilpfc_debugfs_ioktime_data(struct lpfc_vport *vport, char *buf, int size)
139362306a36Sopenharmony_ci{
139462306a36Sopenharmony_ci	struct lpfc_hba   *phba = vport->phba;
139562306a36Sopenharmony_ci	int len = 0;
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci	if (phba->nvmet_support == 0) {
139862306a36Sopenharmony_ci		/* Initiator */
139962306a36Sopenharmony_ci		len += scnprintf(buf + len, PAGE_SIZE - len,
140062306a36Sopenharmony_ci				"ktime %s: Total Samples: %lld\n",
140162306a36Sopenharmony_ci				(phba->ktime_on ?  "Enabled" : "Disabled"),
140262306a36Sopenharmony_ci				phba->ktime_data_samples);
140362306a36Sopenharmony_ci		if (phba->ktime_data_samples == 0)
140462306a36Sopenharmony_ci			return len;
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_ci		len += scnprintf(
140762306a36Sopenharmony_ci			buf + len, PAGE_SIZE - len,
140862306a36Sopenharmony_ci			"Segment 1: Last Cmd cmpl "
140962306a36Sopenharmony_ci			"done -to- Start of next Cmd (in driver)\n");
141062306a36Sopenharmony_ci		len += scnprintf(
141162306a36Sopenharmony_ci			buf + len, PAGE_SIZE - len,
141262306a36Sopenharmony_ci			"avg:%08lld min:%08lld max %08lld\n",
141362306a36Sopenharmony_ci			div_u64(phba->ktime_seg1_total,
141462306a36Sopenharmony_ci				phba->ktime_data_samples),
141562306a36Sopenharmony_ci			phba->ktime_seg1_min,
141662306a36Sopenharmony_ci			phba->ktime_seg1_max);
141762306a36Sopenharmony_ci		len += scnprintf(
141862306a36Sopenharmony_ci			buf + len, PAGE_SIZE - len,
141962306a36Sopenharmony_ci			"Segment 2: Driver start of Cmd "
142062306a36Sopenharmony_ci			"-to- Firmware WQ doorbell\n");
142162306a36Sopenharmony_ci		len += scnprintf(
142262306a36Sopenharmony_ci			buf + len, PAGE_SIZE - len,
142362306a36Sopenharmony_ci			"avg:%08lld min:%08lld max %08lld\n",
142462306a36Sopenharmony_ci			div_u64(phba->ktime_seg2_total,
142562306a36Sopenharmony_ci				phba->ktime_data_samples),
142662306a36Sopenharmony_ci			phba->ktime_seg2_min,
142762306a36Sopenharmony_ci			phba->ktime_seg2_max);
142862306a36Sopenharmony_ci		len += scnprintf(
142962306a36Sopenharmony_ci			buf + len, PAGE_SIZE - len,
143062306a36Sopenharmony_ci			"Segment 3: Firmware WQ doorbell -to- "
143162306a36Sopenharmony_ci			"MSI-X ISR cmpl\n");
143262306a36Sopenharmony_ci		len += scnprintf(
143362306a36Sopenharmony_ci			buf + len, PAGE_SIZE - len,
143462306a36Sopenharmony_ci			"avg:%08lld min:%08lld max %08lld\n",
143562306a36Sopenharmony_ci			div_u64(phba->ktime_seg3_total,
143662306a36Sopenharmony_ci				phba->ktime_data_samples),
143762306a36Sopenharmony_ci			phba->ktime_seg3_min,
143862306a36Sopenharmony_ci			phba->ktime_seg3_max);
143962306a36Sopenharmony_ci		len += scnprintf(
144062306a36Sopenharmony_ci			buf + len, PAGE_SIZE - len,
144162306a36Sopenharmony_ci			"Segment 4: MSI-X ISR cmpl -to- "
144262306a36Sopenharmony_ci			"Cmd cmpl done\n");
144362306a36Sopenharmony_ci		len += scnprintf(
144462306a36Sopenharmony_ci			buf + len, PAGE_SIZE - len,
144562306a36Sopenharmony_ci			"avg:%08lld min:%08lld max %08lld\n",
144662306a36Sopenharmony_ci			div_u64(phba->ktime_seg4_total,
144762306a36Sopenharmony_ci				phba->ktime_data_samples),
144862306a36Sopenharmony_ci			phba->ktime_seg4_min,
144962306a36Sopenharmony_ci			phba->ktime_seg4_max);
145062306a36Sopenharmony_ci		len += scnprintf(
145162306a36Sopenharmony_ci			buf + len, PAGE_SIZE - len,
145262306a36Sopenharmony_ci			"Total IO avg time: %08lld\n",
145362306a36Sopenharmony_ci			div_u64(phba->ktime_seg1_total +
145462306a36Sopenharmony_ci			phba->ktime_seg2_total  +
145562306a36Sopenharmony_ci			phba->ktime_seg3_total +
145662306a36Sopenharmony_ci			phba->ktime_seg4_total,
145762306a36Sopenharmony_ci			phba->ktime_data_samples));
145862306a36Sopenharmony_ci		return len;
145962306a36Sopenharmony_ci	}
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	/* NVME Target */
146262306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
146362306a36Sopenharmony_ci			"ktime %s: Total Samples: %lld %lld\n",
146462306a36Sopenharmony_ci			(phba->ktime_on ? "Enabled" : "Disabled"),
146562306a36Sopenharmony_ci			phba->ktime_data_samples,
146662306a36Sopenharmony_ci			phba->ktime_status_samples);
146762306a36Sopenharmony_ci	if (phba->ktime_data_samples == 0)
146862306a36Sopenharmony_ci		return len;
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
147162306a36Sopenharmony_ci			"Segment 1: MSI-X ISR Rcv cmd -to- "
147262306a36Sopenharmony_ci			"cmd pass to NVME Layer\n");
147362306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
147462306a36Sopenharmony_ci			"avg:%08lld min:%08lld max %08lld\n",
147562306a36Sopenharmony_ci			div_u64(phba->ktime_seg1_total,
147662306a36Sopenharmony_ci				phba->ktime_data_samples),
147762306a36Sopenharmony_ci			phba->ktime_seg1_min,
147862306a36Sopenharmony_ci			phba->ktime_seg1_max);
147962306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
148062306a36Sopenharmony_ci			"Segment 2: cmd pass to NVME Layer- "
148162306a36Sopenharmony_ci			"-to- Driver rcv cmd OP (action)\n");
148262306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
148362306a36Sopenharmony_ci			"avg:%08lld min:%08lld max %08lld\n",
148462306a36Sopenharmony_ci			div_u64(phba->ktime_seg2_total,
148562306a36Sopenharmony_ci				phba->ktime_data_samples),
148662306a36Sopenharmony_ci			phba->ktime_seg2_min,
148762306a36Sopenharmony_ci			phba->ktime_seg2_max);
148862306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
148962306a36Sopenharmony_ci			"Segment 3: Driver rcv cmd OP -to- "
149062306a36Sopenharmony_ci			"Firmware WQ doorbell: cmd\n");
149162306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
149262306a36Sopenharmony_ci			"avg:%08lld min:%08lld max %08lld\n",
149362306a36Sopenharmony_ci			div_u64(phba->ktime_seg3_total,
149462306a36Sopenharmony_ci				phba->ktime_data_samples),
149562306a36Sopenharmony_ci			phba->ktime_seg3_min,
149662306a36Sopenharmony_ci			phba->ktime_seg3_max);
149762306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
149862306a36Sopenharmony_ci			"Segment 4: Firmware WQ doorbell: cmd "
149962306a36Sopenharmony_ci			"-to- MSI-X ISR for cmd cmpl\n");
150062306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
150162306a36Sopenharmony_ci			"avg:%08lld min:%08lld max %08lld\n",
150262306a36Sopenharmony_ci			div_u64(phba->ktime_seg4_total,
150362306a36Sopenharmony_ci				phba->ktime_data_samples),
150462306a36Sopenharmony_ci			phba->ktime_seg4_min,
150562306a36Sopenharmony_ci			phba->ktime_seg4_max);
150662306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
150762306a36Sopenharmony_ci			"Segment 5: MSI-X ISR for cmd cmpl "
150862306a36Sopenharmony_ci			"-to- NVME layer passed cmd done\n");
150962306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
151062306a36Sopenharmony_ci			"avg:%08lld min:%08lld max %08lld\n",
151162306a36Sopenharmony_ci			div_u64(phba->ktime_seg5_total,
151262306a36Sopenharmony_ci				phba->ktime_data_samples),
151362306a36Sopenharmony_ci			phba->ktime_seg5_min,
151462306a36Sopenharmony_ci			phba->ktime_seg5_max);
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_ci	if (phba->ktime_status_samples == 0) {
151762306a36Sopenharmony_ci		len += scnprintf(buf + len, PAGE_SIZE-len,
151862306a36Sopenharmony_ci				"Total: cmd received by MSI-X ISR "
151962306a36Sopenharmony_ci				"-to- cmd completed on wire\n");
152062306a36Sopenharmony_ci		len += scnprintf(buf + len, PAGE_SIZE-len,
152162306a36Sopenharmony_ci				"avg:%08lld min:%08lld "
152262306a36Sopenharmony_ci				"max %08lld\n",
152362306a36Sopenharmony_ci				div_u64(phba->ktime_seg10_total,
152462306a36Sopenharmony_ci					phba->ktime_data_samples),
152562306a36Sopenharmony_ci				phba->ktime_seg10_min,
152662306a36Sopenharmony_ci				phba->ktime_seg10_max);
152762306a36Sopenharmony_ci		return len;
152862306a36Sopenharmony_ci	}
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
153162306a36Sopenharmony_ci			"Segment 6: NVME layer passed cmd done "
153262306a36Sopenharmony_ci			"-to- Driver rcv rsp status OP\n");
153362306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
153462306a36Sopenharmony_ci			"avg:%08lld min:%08lld max %08lld\n",
153562306a36Sopenharmony_ci			div_u64(phba->ktime_seg6_total,
153662306a36Sopenharmony_ci				phba->ktime_status_samples),
153762306a36Sopenharmony_ci			phba->ktime_seg6_min,
153862306a36Sopenharmony_ci			phba->ktime_seg6_max);
153962306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
154062306a36Sopenharmony_ci			"Segment 7: Driver rcv rsp status OP "
154162306a36Sopenharmony_ci			"-to- Firmware WQ doorbell: status\n");
154262306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
154362306a36Sopenharmony_ci			"avg:%08lld min:%08lld max %08lld\n",
154462306a36Sopenharmony_ci			div_u64(phba->ktime_seg7_total,
154562306a36Sopenharmony_ci				phba->ktime_status_samples),
154662306a36Sopenharmony_ci			phba->ktime_seg7_min,
154762306a36Sopenharmony_ci			phba->ktime_seg7_max);
154862306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
154962306a36Sopenharmony_ci			"Segment 8: Firmware WQ doorbell: status"
155062306a36Sopenharmony_ci			" -to- MSI-X ISR for status cmpl\n");
155162306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
155262306a36Sopenharmony_ci			"avg:%08lld min:%08lld max %08lld\n",
155362306a36Sopenharmony_ci			div_u64(phba->ktime_seg8_total,
155462306a36Sopenharmony_ci				phba->ktime_status_samples),
155562306a36Sopenharmony_ci			phba->ktime_seg8_min,
155662306a36Sopenharmony_ci			phba->ktime_seg8_max);
155762306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
155862306a36Sopenharmony_ci			"Segment 9: MSI-X ISR for status cmpl  "
155962306a36Sopenharmony_ci			"-to- NVME layer passed status done\n");
156062306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
156162306a36Sopenharmony_ci			"avg:%08lld min:%08lld max %08lld\n",
156262306a36Sopenharmony_ci			div_u64(phba->ktime_seg9_total,
156362306a36Sopenharmony_ci				phba->ktime_status_samples),
156462306a36Sopenharmony_ci			phba->ktime_seg9_min,
156562306a36Sopenharmony_ci			phba->ktime_seg9_max);
156662306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
156762306a36Sopenharmony_ci			"Total: cmd received by MSI-X ISR -to- "
156862306a36Sopenharmony_ci			"cmd completed on wire\n");
156962306a36Sopenharmony_ci	len += scnprintf(buf + len, PAGE_SIZE-len,
157062306a36Sopenharmony_ci			"avg:%08lld min:%08lld max %08lld\n",
157162306a36Sopenharmony_ci			div_u64(phba->ktime_seg10_total,
157262306a36Sopenharmony_ci				phba->ktime_status_samples),
157362306a36Sopenharmony_ci			phba->ktime_seg10_min,
157462306a36Sopenharmony_ci			phba->ktime_seg10_max);
157562306a36Sopenharmony_ci	return len;
157662306a36Sopenharmony_ci}
157762306a36Sopenharmony_ci
157862306a36Sopenharmony_ci/**
157962306a36Sopenharmony_ci * lpfc_debugfs_nvmeio_trc_data - Dump NVME IO trace list to a buffer
158062306a36Sopenharmony_ci * @phba: The phba to gather target node info from.
158162306a36Sopenharmony_ci * @buf: The buffer to dump log into.
158262306a36Sopenharmony_ci * @size: The maximum amount of data to process.
158362306a36Sopenharmony_ci *
158462306a36Sopenharmony_ci * Description:
158562306a36Sopenharmony_ci * This routine dumps the NVME IO trace associated with @phba
158662306a36Sopenharmony_ci *
158762306a36Sopenharmony_ci * Return Value:
158862306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will
158962306a36Sopenharmony_ci * not exceed @size.
159062306a36Sopenharmony_ci **/
159162306a36Sopenharmony_cistatic int
159262306a36Sopenharmony_cilpfc_debugfs_nvmeio_trc_data(struct lpfc_hba *phba, char *buf, int size)
159362306a36Sopenharmony_ci{
159462306a36Sopenharmony_ci	struct lpfc_debugfs_nvmeio_trc *dtp;
159562306a36Sopenharmony_ci	int i, state, index, skip;
159662306a36Sopenharmony_ci	int len = 0;
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci	state = phba->nvmeio_trc_on;
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	index = (atomic_read(&phba->nvmeio_trc_cnt) + 1) &
160162306a36Sopenharmony_ci		(phba->nvmeio_trc_size - 1);
160262306a36Sopenharmony_ci	skip = phba->nvmeio_trc_output_idx;
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ci	len += scnprintf(buf + len, size - len,
160562306a36Sopenharmony_ci			"%s IO Trace %s: next_idx %d skip %d size %d\n",
160662306a36Sopenharmony_ci			(phba->nvmet_support ? "NVME" : "NVMET"),
160762306a36Sopenharmony_ci			(state ? "Enabled" : "Disabled"),
160862306a36Sopenharmony_ci			index, skip, phba->nvmeio_trc_size);
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	if (!phba->nvmeio_trc || state)
161162306a36Sopenharmony_ci		return len;
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_ci	/* trace MUST bhe off to continue */
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_ci	for (i = index; i < phba->nvmeio_trc_size; i++) {
161662306a36Sopenharmony_ci		if (skip) {
161762306a36Sopenharmony_ci			skip--;
161862306a36Sopenharmony_ci			continue;
161962306a36Sopenharmony_ci		}
162062306a36Sopenharmony_ci		dtp = phba->nvmeio_trc + i;
162162306a36Sopenharmony_ci		phba->nvmeio_trc_output_idx++;
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci		if (!dtp->fmt)
162462306a36Sopenharmony_ci			continue;
162562306a36Sopenharmony_ci
162662306a36Sopenharmony_ci		len +=  scnprintf(buf + len, size - len, dtp->fmt,
162762306a36Sopenharmony_ci			dtp->data1, dtp->data2, dtp->data3);
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci		if (phba->nvmeio_trc_output_idx >= phba->nvmeio_trc_size) {
163062306a36Sopenharmony_ci			phba->nvmeio_trc_output_idx = 0;
163162306a36Sopenharmony_ci			len += scnprintf(buf + len, size - len,
163262306a36Sopenharmony_ci					"Trace Complete\n");
163362306a36Sopenharmony_ci			goto out;
163462306a36Sopenharmony_ci		}
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci		if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ)) {
163762306a36Sopenharmony_ci			len += scnprintf(buf + len, size - len,
163862306a36Sopenharmony_ci					"Trace Continue (%d of %d)\n",
163962306a36Sopenharmony_ci					phba->nvmeio_trc_output_idx,
164062306a36Sopenharmony_ci					phba->nvmeio_trc_size);
164162306a36Sopenharmony_ci			goto out;
164262306a36Sopenharmony_ci		}
164362306a36Sopenharmony_ci	}
164462306a36Sopenharmony_ci	for (i = 0; i < index; i++) {
164562306a36Sopenharmony_ci		if (skip) {
164662306a36Sopenharmony_ci			skip--;
164762306a36Sopenharmony_ci			continue;
164862306a36Sopenharmony_ci		}
164962306a36Sopenharmony_ci		dtp = phba->nvmeio_trc + i;
165062306a36Sopenharmony_ci		phba->nvmeio_trc_output_idx++;
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_ci		if (!dtp->fmt)
165362306a36Sopenharmony_ci			continue;
165462306a36Sopenharmony_ci
165562306a36Sopenharmony_ci		len +=  scnprintf(buf + len, size - len, dtp->fmt,
165662306a36Sopenharmony_ci			dtp->data1, dtp->data2, dtp->data3);
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ci		if (phba->nvmeio_trc_output_idx >= phba->nvmeio_trc_size) {
165962306a36Sopenharmony_ci			phba->nvmeio_trc_output_idx = 0;
166062306a36Sopenharmony_ci			len += scnprintf(buf + len, size - len,
166162306a36Sopenharmony_ci					"Trace Complete\n");
166262306a36Sopenharmony_ci			goto out;
166362306a36Sopenharmony_ci		}
166462306a36Sopenharmony_ci
166562306a36Sopenharmony_ci		if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ)) {
166662306a36Sopenharmony_ci			len += scnprintf(buf + len, size - len,
166762306a36Sopenharmony_ci					"Trace Continue (%d of %d)\n",
166862306a36Sopenharmony_ci					phba->nvmeio_trc_output_idx,
166962306a36Sopenharmony_ci					phba->nvmeio_trc_size);
167062306a36Sopenharmony_ci			goto out;
167162306a36Sopenharmony_ci		}
167262306a36Sopenharmony_ci	}
167362306a36Sopenharmony_ci
167462306a36Sopenharmony_ci	len += scnprintf(buf + len, size - len,
167562306a36Sopenharmony_ci			"Trace Done\n");
167662306a36Sopenharmony_ciout:
167762306a36Sopenharmony_ci	return len;
167862306a36Sopenharmony_ci}
167962306a36Sopenharmony_ci
168062306a36Sopenharmony_ci/**
168162306a36Sopenharmony_ci * lpfc_debugfs_hdwqstat_data - Dump I/O stats to a buffer
168262306a36Sopenharmony_ci * @vport: The vport to gather target node info from.
168362306a36Sopenharmony_ci * @buf: The buffer to dump log into.
168462306a36Sopenharmony_ci * @size: The maximum amount of data to process.
168562306a36Sopenharmony_ci *
168662306a36Sopenharmony_ci * Description:
168762306a36Sopenharmony_ci * This routine dumps the NVME + SCSI statistics associated with @vport
168862306a36Sopenharmony_ci *
168962306a36Sopenharmony_ci * Return Value:
169062306a36Sopenharmony_ci * This routine returns the amount of bytes that were dumped into @buf and will
169162306a36Sopenharmony_ci * not exceed @size.
169262306a36Sopenharmony_ci **/
169362306a36Sopenharmony_cistatic int
169462306a36Sopenharmony_cilpfc_debugfs_hdwqstat_data(struct lpfc_vport *vport, char *buf, int size)
169562306a36Sopenharmony_ci{
169662306a36Sopenharmony_ci	struct lpfc_hba   *phba = vport->phba;
169762306a36Sopenharmony_ci	struct lpfc_hdwq_stat *c_stat;
169862306a36Sopenharmony_ci	int i, j, len;
169962306a36Sopenharmony_ci	uint32_t tot_xmt;
170062306a36Sopenharmony_ci	uint32_t tot_rcv;
170162306a36Sopenharmony_ci	uint32_t tot_cmpl;
170262306a36Sopenharmony_ci	char tmp[LPFC_MAX_SCSI_INFO_TMP_LEN] = {0};
170362306a36Sopenharmony_ci
170462306a36Sopenharmony_ci	scnprintf(tmp, sizeof(tmp), "HDWQ Stats:\n\n");
170562306a36Sopenharmony_ci	if (strlcat(buf, tmp, size) >= size)
170662306a36Sopenharmony_ci		goto buffer_done;
170762306a36Sopenharmony_ci
170862306a36Sopenharmony_ci	scnprintf(tmp, sizeof(tmp), "(NVME Accounting: %s) ",
170962306a36Sopenharmony_ci		  (phba->hdwqstat_on &
171062306a36Sopenharmony_ci		  (LPFC_CHECK_NVME_IO | LPFC_CHECK_NVMET_IO) ?
171162306a36Sopenharmony_ci		  "Enabled" : "Disabled"));
171262306a36Sopenharmony_ci	if (strlcat(buf, tmp, size) >= size)
171362306a36Sopenharmony_ci		goto buffer_done;
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_ci	scnprintf(tmp, sizeof(tmp), "(SCSI Accounting: %s) ",
171662306a36Sopenharmony_ci		  (phba->hdwqstat_on & LPFC_CHECK_SCSI_IO ?
171762306a36Sopenharmony_ci		  "Enabled" : "Disabled"));
171862306a36Sopenharmony_ci	if (strlcat(buf, tmp, size) >= size)
171962306a36Sopenharmony_ci		goto buffer_done;
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci	scnprintf(tmp, sizeof(tmp), "\n\n");
172262306a36Sopenharmony_ci	if (strlcat(buf, tmp, size) >= size)
172362306a36Sopenharmony_ci		goto buffer_done;
172462306a36Sopenharmony_ci
172562306a36Sopenharmony_ci	for (i = 0; i < phba->cfg_hdw_queue; i++) {
172662306a36Sopenharmony_ci		tot_rcv = 0;
172762306a36Sopenharmony_ci		tot_xmt = 0;
172862306a36Sopenharmony_ci		tot_cmpl = 0;
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci		for_each_present_cpu(j) {
173162306a36Sopenharmony_ci			c_stat = per_cpu_ptr(phba->sli4_hba.c_stat, j);
173262306a36Sopenharmony_ci
173362306a36Sopenharmony_ci			/* Only display for this HDWQ */
173462306a36Sopenharmony_ci			if (i != c_stat->hdwq_no)
173562306a36Sopenharmony_ci				continue;
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_ci			/* Only display non-zero counters */
173862306a36Sopenharmony_ci			if (!c_stat->xmt_io && !c_stat->cmpl_io &&
173962306a36Sopenharmony_ci			    !c_stat->rcv_io)
174062306a36Sopenharmony_ci				continue;
174162306a36Sopenharmony_ci
174262306a36Sopenharmony_ci			if (!tot_xmt && !tot_cmpl && !tot_rcv) {
174362306a36Sopenharmony_ci				/* Print HDWQ string only the first time */
174462306a36Sopenharmony_ci				scnprintf(tmp, sizeof(tmp), "[HDWQ %d]:\t", i);
174562306a36Sopenharmony_ci				if (strlcat(buf, tmp, size) >= size)
174662306a36Sopenharmony_ci					goto buffer_done;
174762306a36Sopenharmony_ci			}
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci			tot_xmt += c_stat->xmt_io;
175062306a36Sopenharmony_ci			tot_cmpl += c_stat->cmpl_io;
175162306a36Sopenharmony_ci			if (phba->nvmet_support)
175262306a36Sopenharmony_ci				tot_rcv += c_stat->rcv_io;
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_ci			scnprintf(tmp, sizeof(tmp), "| [CPU %d]: ", j);
175562306a36Sopenharmony_ci			if (strlcat(buf, tmp, size) >= size)
175662306a36Sopenharmony_ci				goto buffer_done;
175762306a36Sopenharmony_ci
175862306a36Sopenharmony_ci			if (phba->nvmet_support) {
175962306a36Sopenharmony_ci				scnprintf(tmp, sizeof(tmp),
176062306a36Sopenharmony_ci					  "XMT 0x%x CMPL 0x%x RCV 0x%x |",
176162306a36Sopenharmony_ci					  c_stat->xmt_io, c_stat->cmpl_io,
176262306a36Sopenharmony_ci					  c_stat->rcv_io);
176362306a36Sopenharmony_ci				if (strlcat(buf, tmp, size) >= size)
176462306a36Sopenharmony_ci					goto buffer_done;
176562306a36Sopenharmony_ci			} else {
176662306a36Sopenharmony_ci				scnprintf(tmp, sizeof(tmp),
176762306a36Sopenharmony_ci					  "XMT 0x%x CMPL 0x%x |",
176862306a36Sopenharmony_ci					  c_stat->xmt_io, c_stat->cmpl_io);
176962306a36Sopenharmony_ci				if (strlcat(buf, tmp, size) >= size)
177062306a36Sopenharmony_ci					goto buffer_done;
177162306a36Sopenharmony_ci			}
177262306a36Sopenharmony_ci		}
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_ci		/* Check if nothing to display */
177562306a36Sopenharmony_ci		if (!tot_xmt && !tot_cmpl && !tot_rcv)
177662306a36Sopenharmony_ci			continue;
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci		scnprintf(tmp, sizeof(tmp), "\t->\t[HDWQ Total: ");
177962306a36Sopenharmony_ci		if (strlcat(buf, tmp, size) >= size)
178062306a36Sopenharmony_ci			goto buffer_done;
178162306a36Sopenharmony_ci
178262306a36Sopenharmony_ci		if (phba->nvmet_support) {
178362306a36Sopenharmony_ci			scnprintf(tmp, sizeof(tmp),
178462306a36Sopenharmony_ci				  "XMT 0x%x CMPL 0x%x RCV 0x%x]\n\n",
178562306a36Sopenharmony_ci				  tot_xmt, tot_cmpl, tot_rcv);
178662306a36Sopenharmony_ci			if (strlcat(buf, tmp, size) >= size)
178762306a36Sopenharmony_ci				goto buffer_done;
178862306a36Sopenharmony_ci		} else {
178962306a36Sopenharmony_ci			scnprintf(tmp, sizeof(tmp),
179062306a36Sopenharmony_ci				  "XMT 0x%x CMPL 0x%x]\n\n",
179162306a36Sopenharmony_ci				  tot_xmt, tot_cmpl);
179262306a36Sopenharmony_ci			if (strlcat(buf, tmp, size) >= size)
179362306a36Sopenharmony_ci				goto buffer_done;
179462306a36Sopenharmony_ci		}
179562306a36Sopenharmony_ci	}
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_cibuffer_done:
179862306a36Sopenharmony_ci	len = strnlen(buf, size);
179962306a36Sopenharmony_ci	return len;
180062306a36Sopenharmony_ci}
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci#endif
180362306a36Sopenharmony_ci
180462306a36Sopenharmony_ci/**
180562306a36Sopenharmony_ci * lpfc_debugfs_disc_trc - Store discovery trace log
180662306a36Sopenharmony_ci * @vport: The vport to associate this trace string with for retrieval.
180762306a36Sopenharmony_ci * @mask: Log entry classification.
180862306a36Sopenharmony_ci * @fmt: Format string to be displayed when dumping the log.
180962306a36Sopenharmony_ci * @data1: 1st data parameter to be applied to @fmt.
181062306a36Sopenharmony_ci * @data2: 2nd data parameter to be applied to @fmt.
181162306a36Sopenharmony_ci * @data3: 3rd data parameter to be applied to @fmt.
181262306a36Sopenharmony_ci *
181362306a36Sopenharmony_ci * Description:
181462306a36Sopenharmony_ci * This routine is used by the driver code to add a debugfs log entry to the
181562306a36Sopenharmony_ci * discovery trace buffer associated with @vport. Only entries with a @mask that
181662306a36Sopenharmony_ci * match the current debugfs discovery mask will be saved. Entries that do not
181762306a36Sopenharmony_ci * match will be thrown away. @fmt, @data1, @data2, and @data3 are used like
181862306a36Sopenharmony_ci * printf when displaying the log.
181962306a36Sopenharmony_ci **/
182062306a36Sopenharmony_ciinline void
182162306a36Sopenharmony_cilpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt,
182262306a36Sopenharmony_ci	uint32_t data1, uint32_t data2, uint32_t data3)
182362306a36Sopenharmony_ci{
182462306a36Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
182562306a36Sopenharmony_ci	struct lpfc_debugfs_trc *dtp;
182662306a36Sopenharmony_ci	int index;
182762306a36Sopenharmony_ci
182862306a36Sopenharmony_ci	if (!(lpfc_debugfs_mask_disc_trc & mask))
182962306a36Sopenharmony_ci		return;
183062306a36Sopenharmony_ci
183162306a36Sopenharmony_ci	if (!lpfc_debugfs_enable || !lpfc_debugfs_max_disc_trc ||
183262306a36Sopenharmony_ci		!vport || !vport->disc_trc)
183362306a36Sopenharmony_ci		return;
183462306a36Sopenharmony_ci
183562306a36Sopenharmony_ci	index = atomic_inc_return(&vport->disc_trc_cnt) &
183662306a36Sopenharmony_ci		(lpfc_debugfs_max_disc_trc - 1);
183762306a36Sopenharmony_ci	dtp = vport->disc_trc + index;
183862306a36Sopenharmony_ci	dtp->fmt = fmt;
183962306a36Sopenharmony_ci	dtp->data1 = data1;
184062306a36Sopenharmony_ci	dtp->data2 = data2;
184162306a36Sopenharmony_ci	dtp->data3 = data3;
184262306a36Sopenharmony_ci	dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt);
184362306a36Sopenharmony_ci	dtp->jif = jiffies;
184462306a36Sopenharmony_ci#endif
184562306a36Sopenharmony_ci	return;
184662306a36Sopenharmony_ci}
184762306a36Sopenharmony_ci
184862306a36Sopenharmony_ci/**
184962306a36Sopenharmony_ci * lpfc_debugfs_slow_ring_trc - Store slow ring trace log
185062306a36Sopenharmony_ci * @phba: The phba to associate this trace string with for retrieval.
185162306a36Sopenharmony_ci * @fmt: Format string to be displayed when dumping the log.
185262306a36Sopenharmony_ci * @data1: 1st data parameter to be applied to @fmt.
185362306a36Sopenharmony_ci * @data2: 2nd data parameter to be applied to @fmt.
185462306a36Sopenharmony_ci * @data3: 3rd data parameter to be applied to @fmt.
185562306a36Sopenharmony_ci *
185662306a36Sopenharmony_ci * Description:
185762306a36Sopenharmony_ci * This routine is used by the driver code to add a debugfs log entry to the
185862306a36Sopenharmony_ci * discovery trace buffer associated with @vport. @fmt, @data1, @data2, and
185962306a36Sopenharmony_ci * @data3 are used like printf when displaying the log.
186062306a36Sopenharmony_ci **/
186162306a36Sopenharmony_ciinline void
186262306a36Sopenharmony_cilpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt,
186362306a36Sopenharmony_ci	uint32_t data1, uint32_t data2, uint32_t data3)
186462306a36Sopenharmony_ci{
186562306a36Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
186662306a36Sopenharmony_ci	struct lpfc_debugfs_trc *dtp;
186762306a36Sopenharmony_ci	int index;
186862306a36Sopenharmony_ci
186962306a36Sopenharmony_ci	if (!lpfc_debugfs_enable || !lpfc_debugfs_max_slow_ring_trc ||
187062306a36Sopenharmony_ci		!phba || !phba->slow_ring_trc)
187162306a36Sopenharmony_ci		return;
187262306a36Sopenharmony_ci
187362306a36Sopenharmony_ci	index = atomic_inc_return(&phba->slow_ring_trc_cnt) &
187462306a36Sopenharmony_ci		(lpfc_debugfs_max_slow_ring_trc - 1);
187562306a36Sopenharmony_ci	dtp = phba->slow_ring_trc + index;
187662306a36Sopenharmony_ci	dtp->fmt = fmt;
187762306a36Sopenharmony_ci	dtp->data1 = data1;
187862306a36Sopenharmony_ci	dtp->data2 = data2;
187962306a36Sopenharmony_ci	dtp->data3 = data3;
188062306a36Sopenharmony_ci	dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt);
188162306a36Sopenharmony_ci	dtp->jif = jiffies;
188262306a36Sopenharmony_ci#endif
188362306a36Sopenharmony_ci	return;
188462306a36Sopenharmony_ci}
188562306a36Sopenharmony_ci
188662306a36Sopenharmony_ci/**
188762306a36Sopenharmony_ci * lpfc_debugfs_nvme_trc - Store NVME/NVMET trace log
188862306a36Sopenharmony_ci * @phba: The phba to associate this trace string with for retrieval.
188962306a36Sopenharmony_ci * @fmt: Format string to be displayed when dumping the log.
189062306a36Sopenharmony_ci * @data1: 1st data parameter to be applied to @fmt.
189162306a36Sopenharmony_ci * @data2: 2nd data parameter to be applied to @fmt.
189262306a36Sopenharmony_ci * @data3: 3rd data parameter to be applied to @fmt.
189362306a36Sopenharmony_ci *
189462306a36Sopenharmony_ci * Description:
189562306a36Sopenharmony_ci * This routine is used by the driver code to add a debugfs log entry to the
189662306a36Sopenharmony_ci * nvme trace buffer associated with @phba. @fmt, @data1, @data2, and
189762306a36Sopenharmony_ci * @data3 are used like printf when displaying the log.
189862306a36Sopenharmony_ci **/
189962306a36Sopenharmony_ciinline void
190062306a36Sopenharmony_cilpfc_debugfs_nvme_trc(struct lpfc_hba *phba, char *fmt,
190162306a36Sopenharmony_ci		      uint16_t data1, uint16_t data2, uint32_t data3)
190262306a36Sopenharmony_ci{
190362306a36Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
190462306a36Sopenharmony_ci	struct lpfc_debugfs_nvmeio_trc *dtp;
190562306a36Sopenharmony_ci	int index;
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	if (!phba->nvmeio_trc_on || !phba->nvmeio_trc)
190862306a36Sopenharmony_ci		return;
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci	index = atomic_inc_return(&phba->nvmeio_trc_cnt) &
191162306a36Sopenharmony_ci		(phba->nvmeio_trc_size - 1);
191262306a36Sopenharmony_ci	dtp = phba->nvmeio_trc + index;
191362306a36Sopenharmony_ci	dtp->fmt = fmt;
191462306a36Sopenharmony_ci	dtp->data1 = data1;
191562306a36Sopenharmony_ci	dtp->data2 = data2;
191662306a36Sopenharmony_ci	dtp->data3 = data3;
191762306a36Sopenharmony_ci#endif
191862306a36Sopenharmony_ci}
191962306a36Sopenharmony_ci
192062306a36Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
192162306a36Sopenharmony_ci/**
192262306a36Sopenharmony_ci * lpfc_debugfs_disc_trc_open - Open the discovery trace log
192362306a36Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer.
192462306a36Sopenharmony_ci * @file: The file pointer to attach the log output.
192562306a36Sopenharmony_ci *
192662306a36Sopenharmony_ci * Description:
192762306a36Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets
192862306a36Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer
192962306a36Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then
193062306a36Sopenharmony_ci * returns a pointer to that log in the private_data field in @file.
193162306a36Sopenharmony_ci *
193262306a36Sopenharmony_ci * Returns:
193362306a36Sopenharmony_ci * This function returns zero if successful. On error it will return a negative
193462306a36Sopenharmony_ci * error value.
193562306a36Sopenharmony_ci **/
193662306a36Sopenharmony_cistatic int
193762306a36Sopenharmony_cilpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file)
193862306a36Sopenharmony_ci{
193962306a36Sopenharmony_ci	struct lpfc_vport *vport = inode->i_private;
194062306a36Sopenharmony_ci	struct lpfc_debug *debug;
194162306a36Sopenharmony_ci	int size;
194262306a36Sopenharmony_ci	int rc = -ENOMEM;
194362306a36Sopenharmony_ci
194462306a36Sopenharmony_ci	if (!lpfc_debugfs_max_disc_trc) {
194562306a36Sopenharmony_ci		rc = -ENOSPC;
194662306a36Sopenharmony_ci		goto out;
194762306a36Sopenharmony_ci	}
194862306a36Sopenharmony_ci
194962306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
195062306a36Sopenharmony_ci	if (!debug)
195162306a36Sopenharmony_ci		goto out;
195262306a36Sopenharmony_ci
195362306a36Sopenharmony_ci	/* Round to page boundary */
195462306a36Sopenharmony_ci	size =  (lpfc_debugfs_max_disc_trc * LPFC_DEBUG_TRC_ENTRY_SIZE);
195562306a36Sopenharmony_ci	size = PAGE_ALIGN(size);
195662306a36Sopenharmony_ci
195762306a36Sopenharmony_ci	debug->buffer = kmalloc(size, GFP_KERNEL);
195862306a36Sopenharmony_ci	if (!debug->buffer) {
195962306a36Sopenharmony_ci		kfree(debug);
196062306a36Sopenharmony_ci		goto out;
196162306a36Sopenharmony_ci	}
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_ci	debug->len = lpfc_debugfs_disc_trc_data(vport, debug->buffer, size);
196462306a36Sopenharmony_ci	file->private_data = debug;
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci	rc = 0;
196762306a36Sopenharmony_ciout:
196862306a36Sopenharmony_ci	return rc;
196962306a36Sopenharmony_ci}
197062306a36Sopenharmony_ci
197162306a36Sopenharmony_ci/**
197262306a36Sopenharmony_ci * lpfc_debugfs_slow_ring_trc_open - Open the Slow Ring trace log
197362306a36Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer.
197462306a36Sopenharmony_ci * @file: The file pointer to attach the log output.
197562306a36Sopenharmony_ci *
197662306a36Sopenharmony_ci * Description:
197762306a36Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets
197862306a36Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer
197962306a36Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then
198062306a36Sopenharmony_ci * returns a pointer to that log in the private_data field in @file.
198162306a36Sopenharmony_ci *
198262306a36Sopenharmony_ci * Returns:
198362306a36Sopenharmony_ci * This function returns zero if successful. On error it will return a negative
198462306a36Sopenharmony_ci * error value.
198562306a36Sopenharmony_ci **/
198662306a36Sopenharmony_cistatic int
198762306a36Sopenharmony_cilpfc_debugfs_slow_ring_trc_open(struct inode *inode, struct file *file)
198862306a36Sopenharmony_ci{
198962306a36Sopenharmony_ci	struct lpfc_hba *phba = inode->i_private;
199062306a36Sopenharmony_ci	struct lpfc_debug *debug;
199162306a36Sopenharmony_ci	int size;
199262306a36Sopenharmony_ci	int rc = -ENOMEM;
199362306a36Sopenharmony_ci
199462306a36Sopenharmony_ci	if (!lpfc_debugfs_max_slow_ring_trc) {
199562306a36Sopenharmony_ci		rc = -ENOSPC;
199662306a36Sopenharmony_ci		goto out;
199762306a36Sopenharmony_ci	}
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
200062306a36Sopenharmony_ci	if (!debug)
200162306a36Sopenharmony_ci		goto out;
200262306a36Sopenharmony_ci
200362306a36Sopenharmony_ci	/* Round to page boundary */
200462306a36Sopenharmony_ci	size =  (lpfc_debugfs_max_slow_ring_trc * LPFC_DEBUG_TRC_ENTRY_SIZE);
200562306a36Sopenharmony_ci	size = PAGE_ALIGN(size);
200662306a36Sopenharmony_ci
200762306a36Sopenharmony_ci	debug->buffer = kmalloc(size, GFP_KERNEL);
200862306a36Sopenharmony_ci	if (!debug->buffer) {
200962306a36Sopenharmony_ci		kfree(debug);
201062306a36Sopenharmony_ci		goto out;
201162306a36Sopenharmony_ci	}
201262306a36Sopenharmony_ci
201362306a36Sopenharmony_ci	debug->len = lpfc_debugfs_slow_ring_trc_data(phba, debug->buffer, size);
201462306a36Sopenharmony_ci	file->private_data = debug;
201562306a36Sopenharmony_ci
201662306a36Sopenharmony_ci	rc = 0;
201762306a36Sopenharmony_ciout:
201862306a36Sopenharmony_ci	return rc;
201962306a36Sopenharmony_ci}
202062306a36Sopenharmony_ci
202162306a36Sopenharmony_ci/**
202262306a36Sopenharmony_ci * lpfc_debugfs_hbqinfo_open - Open the hbqinfo debugfs buffer
202362306a36Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer.
202462306a36Sopenharmony_ci * @file: The file pointer to attach the log output.
202562306a36Sopenharmony_ci *
202662306a36Sopenharmony_ci * Description:
202762306a36Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets
202862306a36Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer
202962306a36Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then
203062306a36Sopenharmony_ci * returns a pointer to that log in the private_data field in @file.
203162306a36Sopenharmony_ci *
203262306a36Sopenharmony_ci * Returns:
203362306a36Sopenharmony_ci * This function returns zero if successful. On error it will return a negative
203462306a36Sopenharmony_ci * error value.
203562306a36Sopenharmony_ci **/
203662306a36Sopenharmony_cistatic int
203762306a36Sopenharmony_cilpfc_debugfs_hbqinfo_open(struct inode *inode, struct file *file)
203862306a36Sopenharmony_ci{
203962306a36Sopenharmony_ci	struct lpfc_hba *phba = inode->i_private;
204062306a36Sopenharmony_ci	struct lpfc_debug *debug;
204162306a36Sopenharmony_ci	int rc = -ENOMEM;
204262306a36Sopenharmony_ci
204362306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
204462306a36Sopenharmony_ci	if (!debug)
204562306a36Sopenharmony_ci		goto out;
204662306a36Sopenharmony_ci
204762306a36Sopenharmony_ci	/* Round to page boundary */
204862306a36Sopenharmony_ci	debug->buffer = kmalloc(LPFC_HBQINFO_SIZE, GFP_KERNEL);
204962306a36Sopenharmony_ci	if (!debug->buffer) {
205062306a36Sopenharmony_ci		kfree(debug);
205162306a36Sopenharmony_ci		goto out;
205262306a36Sopenharmony_ci	}
205362306a36Sopenharmony_ci
205462306a36Sopenharmony_ci	debug->len = lpfc_debugfs_hbqinfo_data(phba, debug->buffer,
205562306a36Sopenharmony_ci		LPFC_HBQINFO_SIZE);
205662306a36Sopenharmony_ci	file->private_data = debug;
205762306a36Sopenharmony_ci
205862306a36Sopenharmony_ci	rc = 0;
205962306a36Sopenharmony_ciout:
206062306a36Sopenharmony_ci	return rc;
206162306a36Sopenharmony_ci}
206262306a36Sopenharmony_ci
206362306a36Sopenharmony_ci/**
206462306a36Sopenharmony_ci * lpfc_debugfs_multixripools_open - Open the multixripool debugfs buffer
206562306a36Sopenharmony_ci * @inode: The inode pointer that contains a hba pointer.
206662306a36Sopenharmony_ci * @file: The file pointer to attach the log output.
206762306a36Sopenharmony_ci *
206862306a36Sopenharmony_ci * Description:
206962306a36Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets
207062306a36Sopenharmony_ci * the hba from the i_private field in @inode, allocates the necessary buffer
207162306a36Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this hba, and then
207262306a36Sopenharmony_ci * returns a pointer to that log in the private_data field in @file.
207362306a36Sopenharmony_ci *
207462306a36Sopenharmony_ci * Returns:
207562306a36Sopenharmony_ci * This function returns zero if successful. On error it will return a negative
207662306a36Sopenharmony_ci * error value.
207762306a36Sopenharmony_ci **/
207862306a36Sopenharmony_cistatic int
207962306a36Sopenharmony_cilpfc_debugfs_multixripools_open(struct inode *inode, struct file *file)
208062306a36Sopenharmony_ci{
208162306a36Sopenharmony_ci	struct lpfc_hba *phba = inode->i_private;
208262306a36Sopenharmony_ci	struct lpfc_debug *debug;
208362306a36Sopenharmony_ci	int rc = -ENOMEM;
208462306a36Sopenharmony_ci
208562306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
208662306a36Sopenharmony_ci	if (!debug)
208762306a36Sopenharmony_ci		goto out;
208862306a36Sopenharmony_ci
208962306a36Sopenharmony_ci	/* Round to page boundary */
209062306a36Sopenharmony_ci	debug->buffer = kzalloc(LPFC_DUMP_MULTIXRIPOOL_SIZE, GFP_KERNEL);
209162306a36Sopenharmony_ci	if (!debug->buffer) {
209262306a36Sopenharmony_ci		kfree(debug);
209362306a36Sopenharmony_ci		goto out;
209462306a36Sopenharmony_ci	}
209562306a36Sopenharmony_ci
209662306a36Sopenharmony_ci	debug->len = lpfc_debugfs_multixripools_data(
209762306a36Sopenharmony_ci		phba, debug->buffer, LPFC_DUMP_MULTIXRIPOOL_SIZE);
209862306a36Sopenharmony_ci
209962306a36Sopenharmony_ci	debug->i_private = inode->i_private;
210062306a36Sopenharmony_ci	file->private_data = debug;
210162306a36Sopenharmony_ci
210262306a36Sopenharmony_ci	rc = 0;
210362306a36Sopenharmony_ciout:
210462306a36Sopenharmony_ci	return rc;
210562306a36Sopenharmony_ci}
210662306a36Sopenharmony_ci
210762306a36Sopenharmony_ci#ifdef LPFC_HDWQ_LOCK_STAT
210862306a36Sopenharmony_ci/**
210962306a36Sopenharmony_ci * lpfc_debugfs_lockstat_open - Open the lockstat debugfs buffer
211062306a36Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer.
211162306a36Sopenharmony_ci * @file: The file pointer to attach the log output.
211262306a36Sopenharmony_ci *
211362306a36Sopenharmony_ci * Description:
211462306a36Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets
211562306a36Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer
211662306a36Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then
211762306a36Sopenharmony_ci * returns a pointer to that log in the private_data field in @file.
211862306a36Sopenharmony_ci *
211962306a36Sopenharmony_ci * Returns:
212062306a36Sopenharmony_ci * This function returns zero if successful. On error it will return a negative
212162306a36Sopenharmony_ci * error value.
212262306a36Sopenharmony_ci **/
212362306a36Sopenharmony_cistatic int
212462306a36Sopenharmony_cilpfc_debugfs_lockstat_open(struct inode *inode, struct file *file)
212562306a36Sopenharmony_ci{
212662306a36Sopenharmony_ci	struct lpfc_hba *phba = inode->i_private;
212762306a36Sopenharmony_ci	struct lpfc_debug *debug;
212862306a36Sopenharmony_ci	int rc = -ENOMEM;
212962306a36Sopenharmony_ci
213062306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
213162306a36Sopenharmony_ci	if (!debug)
213262306a36Sopenharmony_ci		goto out;
213362306a36Sopenharmony_ci
213462306a36Sopenharmony_ci	/* Round to page boundary */
213562306a36Sopenharmony_ci	debug->buffer = kmalloc(LPFC_HDWQINFO_SIZE, GFP_KERNEL);
213662306a36Sopenharmony_ci	if (!debug->buffer) {
213762306a36Sopenharmony_ci		kfree(debug);
213862306a36Sopenharmony_ci		goto out;
213962306a36Sopenharmony_ci	}
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_ci	debug->len = lpfc_debugfs_lockstat_data(phba, debug->buffer,
214262306a36Sopenharmony_ci		LPFC_HBQINFO_SIZE);
214362306a36Sopenharmony_ci	file->private_data = debug;
214462306a36Sopenharmony_ci
214562306a36Sopenharmony_ci	rc = 0;
214662306a36Sopenharmony_ciout:
214762306a36Sopenharmony_ci	return rc;
214862306a36Sopenharmony_ci}
214962306a36Sopenharmony_ci
215062306a36Sopenharmony_cistatic ssize_t
215162306a36Sopenharmony_cilpfc_debugfs_lockstat_write(struct file *file, const char __user *buf,
215262306a36Sopenharmony_ci			    size_t nbytes, loff_t *ppos)
215362306a36Sopenharmony_ci{
215462306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
215562306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
215662306a36Sopenharmony_ci	struct lpfc_sli4_hdw_queue *qp;
215762306a36Sopenharmony_ci	char mybuf[64];
215862306a36Sopenharmony_ci	char *pbuf;
215962306a36Sopenharmony_ci	int i;
216062306a36Sopenharmony_ci	size_t bsize;
216162306a36Sopenharmony_ci
216262306a36Sopenharmony_ci	memset(mybuf, 0, sizeof(mybuf));
216362306a36Sopenharmony_ci
216462306a36Sopenharmony_ci	bsize = min(nbytes, (sizeof(mybuf) - 1));
216562306a36Sopenharmony_ci
216662306a36Sopenharmony_ci	if (copy_from_user(mybuf, buf, bsize))
216762306a36Sopenharmony_ci		return -EFAULT;
216862306a36Sopenharmony_ci	pbuf = &mybuf[0];
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_ci	if ((strncmp(pbuf, "reset", strlen("reset")) == 0) ||
217162306a36Sopenharmony_ci	    (strncmp(pbuf, "zero", strlen("zero")) == 0)) {
217262306a36Sopenharmony_ci		for (i = 0; i < phba->cfg_hdw_queue; i++) {
217362306a36Sopenharmony_ci			qp = &phba->sli4_hba.hdwq[i];
217462306a36Sopenharmony_ci			qp->lock_conflict.alloc_xri_get = 0;
217562306a36Sopenharmony_ci			qp->lock_conflict.alloc_xri_put = 0;
217662306a36Sopenharmony_ci			qp->lock_conflict.free_xri = 0;
217762306a36Sopenharmony_ci			qp->lock_conflict.wq_access = 0;
217862306a36Sopenharmony_ci			qp->lock_conflict.alloc_pvt_pool = 0;
217962306a36Sopenharmony_ci			qp->lock_conflict.mv_from_pvt_pool = 0;
218062306a36Sopenharmony_ci			qp->lock_conflict.mv_to_pub_pool = 0;
218162306a36Sopenharmony_ci			qp->lock_conflict.mv_to_pvt_pool = 0;
218262306a36Sopenharmony_ci			qp->lock_conflict.free_pvt_pool = 0;
218362306a36Sopenharmony_ci			qp->lock_conflict.free_pub_pool = 0;
218462306a36Sopenharmony_ci			qp->lock_conflict.wq_access = 0;
218562306a36Sopenharmony_ci		}
218662306a36Sopenharmony_ci	}
218762306a36Sopenharmony_ci	return bsize;
218862306a36Sopenharmony_ci}
218962306a36Sopenharmony_ci#endif
219062306a36Sopenharmony_ci
219162306a36Sopenharmony_cistatic int lpfc_debugfs_ras_log_data(struct lpfc_hba *phba,
219262306a36Sopenharmony_ci				     char *buffer, int size)
219362306a36Sopenharmony_ci{
219462306a36Sopenharmony_ci	int copied = 0;
219562306a36Sopenharmony_ci	struct lpfc_dmabuf *dmabuf, *next;
219662306a36Sopenharmony_ci
219762306a36Sopenharmony_ci	memset(buffer, 0, size);
219862306a36Sopenharmony_ci
219962306a36Sopenharmony_ci	spin_lock_irq(&phba->hbalock);
220062306a36Sopenharmony_ci	if (phba->ras_fwlog.state != ACTIVE) {
220162306a36Sopenharmony_ci		spin_unlock_irq(&phba->hbalock);
220262306a36Sopenharmony_ci		return -EINVAL;
220362306a36Sopenharmony_ci	}
220462306a36Sopenharmony_ci	spin_unlock_irq(&phba->hbalock);
220562306a36Sopenharmony_ci
220662306a36Sopenharmony_ci	list_for_each_entry_safe(dmabuf, next,
220762306a36Sopenharmony_ci				 &phba->ras_fwlog.fwlog_buff_list, list) {
220862306a36Sopenharmony_ci		/* Check if copying will go over size and a '\0' char */
220962306a36Sopenharmony_ci		if ((copied + LPFC_RAS_MAX_ENTRY_SIZE) >= (size - 1)) {
221062306a36Sopenharmony_ci			memcpy(buffer + copied, dmabuf->virt,
221162306a36Sopenharmony_ci			       size - copied - 1);
221262306a36Sopenharmony_ci			copied += size - copied - 1;
221362306a36Sopenharmony_ci			break;
221462306a36Sopenharmony_ci		}
221562306a36Sopenharmony_ci		memcpy(buffer + copied, dmabuf->virt, LPFC_RAS_MAX_ENTRY_SIZE);
221662306a36Sopenharmony_ci		copied += LPFC_RAS_MAX_ENTRY_SIZE;
221762306a36Sopenharmony_ci	}
221862306a36Sopenharmony_ci	return copied;
221962306a36Sopenharmony_ci}
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_cistatic int
222262306a36Sopenharmony_cilpfc_debugfs_ras_log_release(struct inode *inode, struct file *file)
222362306a36Sopenharmony_ci{
222462306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
222562306a36Sopenharmony_ci
222662306a36Sopenharmony_ci	vfree(debug->buffer);
222762306a36Sopenharmony_ci	kfree(debug);
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_ci	return 0;
223062306a36Sopenharmony_ci}
223162306a36Sopenharmony_ci
223262306a36Sopenharmony_ci/**
223362306a36Sopenharmony_ci * lpfc_debugfs_ras_log_open - Open the RAS log debugfs buffer
223462306a36Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer.
223562306a36Sopenharmony_ci * @file: The file pointer to attach the log output.
223662306a36Sopenharmony_ci *
223762306a36Sopenharmony_ci * Description:
223862306a36Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets
223962306a36Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer
224062306a36Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then
224162306a36Sopenharmony_ci * returns a pointer to that log in the private_data field in @file.
224262306a36Sopenharmony_ci *
224362306a36Sopenharmony_ci * Returns:
224462306a36Sopenharmony_ci * This function returns zero if successful. On error it will return a negative
224562306a36Sopenharmony_ci * error value.
224662306a36Sopenharmony_ci **/
224762306a36Sopenharmony_cistatic int
224862306a36Sopenharmony_cilpfc_debugfs_ras_log_open(struct inode *inode, struct file *file)
224962306a36Sopenharmony_ci{
225062306a36Sopenharmony_ci	struct lpfc_hba *phba = inode->i_private;
225162306a36Sopenharmony_ci	struct lpfc_debug *debug;
225262306a36Sopenharmony_ci	int size;
225362306a36Sopenharmony_ci	int rc = -ENOMEM;
225462306a36Sopenharmony_ci
225562306a36Sopenharmony_ci	spin_lock_irq(&phba->hbalock);
225662306a36Sopenharmony_ci	if (phba->ras_fwlog.state != ACTIVE) {
225762306a36Sopenharmony_ci		spin_unlock_irq(&phba->hbalock);
225862306a36Sopenharmony_ci		rc = -EINVAL;
225962306a36Sopenharmony_ci		goto out;
226062306a36Sopenharmony_ci	}
226162306a36Sopenharmony_ci	spin_unlock_irq(&phba->hbalock);
226262306a36Sopenharmony_ci
226362306a36Sopenharmony_ci	if (check_mul_overflow(LPFC_RAS_MIN_BUFF_POST_SIZE,
226462306a36Sopenharmony_ci			       phba->cfg_ras_fwlog_buffsize, &size))
226562306a36Sopenharmony_ci		goto out;
226662306a36Sopenharmony_ci
226762306a36Sopenharmony_ci	debug = kzalloc(sizeof(*debug), GFP_KERNEL);
226862306a36Sopenharmony_ci	if (!debug)
226962306a36Sopenharmony_ci		goto out;
227062306a36Sopenharmony_ci
227162306a36Sopenharmony_ci	debug->buffer = vmalloc(size);
227262306a36Sopenharmony_ci	if (!debug->buffer)
227362306a36Sopenharmony_ci		goto free_debug;
227462306a36Sopenharmony_ci
227562306a36Sopenharmony_ci	debug->len = lpfc_debugfs_ras_log_data(phba, debug->buffer, size);
227662306a36Sopenharmony_ci	if (debug->len < 0) {
227762306a36Sopenharmony_ci		rc = -EINVAL;
227862306a36Sopenharmony_ci		goto free_buffer;
227962306a36Sopenharmony_ci	}
228062306a36Sopenharmony_ci	file->private_data = debug;
228162306a36Sopenharmony_ci
228262306a36Sopenharmony_ci	return 0;
228362306a36Sopenharmony_ci
228462306a36Sopenharmony_cifree_buffer:
228562306a36Sopenharmony_ci	vfree(debug->buffer);
228662306a36Sopenharmony_cifree_debug:
228762306a36Sopenharmony_ci	kfree(debug);
228862306a36Sopenharmony_ciout:
228962306a36Sopenharmony_ci	return rc;
229062306a36Sopenharmony_ci}
229162306a36Sopenharmony_ci
229262306a36Sopenharmony_ci/**
229362306a36Sopenharmony_ci * lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer
229462306a36Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer.
229562306a36Sopenharmony_ci * @file: The file pointer to attach the log output.
229662306a36Sopenharmony_ci *
229762306a36Sopenharmony_ci * Description:
229862306a36Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets
229962306a36Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer
230062306a36Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then
230162306a36Sopenharmony_ci * returns a pointer to that log in the private_data field in @file.
230262306a36Sopenharmony_ci *
230362306a36Sopenharmony_ci * Returns:
230462306a36Sopenharmony_ci * This function returns zero if successful. On error it will return a negative
230562306a36Sopenharmony_ci * error value.
230662306a36Sopenharmony_ci **/
230762306a36Sopenharmony_cistatic int
230862306a36Sopenharmony_cilpfc_debugfs_dumpHBASlim_open(struct inode *inode, struct file *file)
230962306a36Sopenharmony_ci{
231062306a36Sopenharmony_ci	struct lpfc_hba *phba = inode->i_private;
231162306a36Sopenharmony_ci	struct lpfc_debug *debug;
231262306a36Sopenharmony_ci	int rc = -ENOMEM;
231362306a36Sopenharmony_ci
231462306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
231562306a36Sopenharmony_ci	if (!debug)
231662306a36Sopenharmony_ci		goto out;
231762306a36Sopenharmony_ci
231862306a36Sopenharmony_ci	/* Round to page boundary */
231962306a36Sopenharmony_ci	debug->buffer = kmalloc(LPFC_DUMPHBASLIM_SIZE, GFP_KERNEL);
232062306a36Sopenharmony_ci	if (!debug->buffer) {
232162306a36Sopenharmony_ci		kfree(debug);
232262306a36Sopenharmony_ci		goto out;
232362306a36Sopenharmony_ci	}
232462306a36Sopenharmony_ci
232562306a36Sopenharmony_ci	debug->len = lpfc_debugfs_dumpHBASlim_data(phba, debug->buffer,
232662306a36Sopenharmony_ci		LPFC_DUMPHBASLIM_SIZE);
232762306a36Sopenharmony_ci	file->private_data = debug;
232862306a36Sopenharmony_ci
232962306a36Sopenharmony_ci	rc = 0;
233062306a36Sopenharmony_ciout:
233162306a36Sopenharmony_ci	return rc;
233262306a36Sopenharmony_ci}
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci/**
233562306a36Sopenharmony_ci * lpfc_debugfs_dumpHostSlim_open - Open the Dump Host SLIM debugfs buffer
233662306a36Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer.
233762306a36Sopenharmony_ci * @file: The file pointer to attach the log output.
233862306a36Sopenharmony_ci *
233962306a36Sopenharmony_ci * Description:
234062306a36Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets
234162306a36Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer
234262306a36Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then
234362306a36Sopenharmony_ci * returns a pointer to that log in the private_data field in @file.
234462306a36Sopenharmony_ci *
234562306a36Sopenharmony_ci * Returns:
234662306a36Sopenharmony_ci * This function returns zero if successful. On error it will return a negative
234762306a36Sopenharmony_ci * error value.
234862306a36Sopenharmony_ci **/
234962306a36Sopenharmony_cistatic int
235062306a36Sopenharmony_cilpfc_debugfs_dumpHostSlim_open(struct inode *inode, struct file *file)
235162306a36Sopenharmony_ci{
235262306a36Sopenharmony_ci	struct lpfc_hba *phba = inode->i_private;
235362306a36Sopenharmony_ci	struct lpfc_debug *debug;
235462306a36Sopenharmony_ci	int rc = -ENOMEM;
235562306a36Sopenharmony_ci
235662306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
235762306a36Sopenharmony_ci	if (!debug)
235862306a36Sopenharmony_ci		goto out;
235962306a36Sopenharmony_ci
236062306a36Sopenharmony_ci	/* Round to page boundary */
236162306a36Sopenharmony_ci	debug->buffer = kmalloc(LPFC_DUMPHOSTSLIM_SIZE, GFP_KERNEL);
236262306a36Sopenharmony_ci	if (!debug->buffer) {
236362306a36Sopenharmony_ci		kfree(debug);
236462306a36Sopenharmony_ci		goto out;
236562306a36Sopenharmony_ci	}
236662306a36Sopenharmony_ci
236762306a36Sopenharmony_ci	debug->len = lpfc_debugfs_dumpHostSlim_data(phba, debug->buffer,
236862306a36Sopenharmony_ci		LPFC_DUMPHOSTSLIM_SIZE);
236962306a36Sopenharmony_ci	file->private_data = debug;
237062306a36Sopenharmony_ci
237162306a36Sopenharmony_ci	rc = 0;
237262306a36Sopenharmony_ciout:
237362306a36Sopenharmony_ci	return rc;
237462306a36Sopenharmony_ci}
237562306a36Sopenharmony_ci
237662306a36Sopenharmony_cistatic ssize_t
237762306a36Sopenharmony_cilpfc_debugfs_dif_err_read(struct file *file, char __user *buf,
237862306a36Sopenharmony_ci	size_t nbytes, loff_t *ppos)
237962306a36Sopenharmony_ci{
238062306a36Sopenharmony_ci	struct dentry *dent = file->f_path.dentry;
238162306a36Sopenharmony_ci	struct lpfc_hba *phba = file->private_data;
238262306a36Sopenharmony_ci	char cbuf[32];
238362306a36Sopenharmony_ci	uint64_t tmp = 0;
238462306a36Sopenharmony_ci	int cnt = 0;
238562306a36Sopenharmony_ci
238662306a36Sopenharmony_ci	if (dent == phba->debug_writeGuard)
238762306a36Sopenharmony_ci		cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wgrd_cnt);
238862306a36Sopenharmony_ci	else if (dent == phba->debug_writeApp)
238962306a36Sopenharmony_ci		cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wapp_cnt);
239062306a36Sopenharmony_ci	else if (dent == phba->debug_writeRef)
239162306a36Sopenharmony_ci		cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wref_cnt);
239262306a36Sopenharmony_ci	else if (dent == phba->debug_readGuard)
239362306a36Sopenharmony_ci		cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rgrd_cnt);
239462306a36Sopenharmony_ci	else if (dent == phba->debug_readApp)
239562306a36Sopenharmony_ci		cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rapp_cnt);
239662306a36Sopenharmony_ci	else if (dent == phba->debug_readRef)
239762306a36Sopenharmony_ci		cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rref_cnt);
239862306a36Sopenharmony_ci	else if (dent == phba->debug_InjErrNPortID)
239962306a36Sopenharmony_ci		cnt = scnprintf(cbuf, 32, "0x%06x\n",
240062306a36Sopenharmony_ci				phba->lpfc_injerr_nportid);
240162306a36Sopenharmony_ci	else if (dent == phba->debug_InjErrWWPN) {
240262306a36Sopenharmony_ci		memcpy(&tmp, &phba->lpfc_injerr_wwpn, sizeof(struct lpfc_name));
240362306a36Sopenharmony_ci		tmp = cpu_to_be64(tmp);
240462306a36Sopenharmony_ci		cnt = scnprintf(cbuf, 32, "0x%016llx\n", tmp);
240562306a36Sopenharmony_ci	} else if (dent == phba->debug_InjErrLBA) {
240662306a36Sopenharmony_ci		if (phba->lpfc_injerr_lba == (sector_t)(-1))
240762306a36Sopenharmony_ci			cnt = scnprintf(cbuf, 32, "off\n");
240862306a36Sopenharmony_ci		else
240962306a36Sopenharmony_ci			cnt = scnprintf(cbuf, 32, "0x%llx\n",
241062306a36Sopenharmony_ci				 (uint64_t) phba->lpfc_injerr_lba);
241162306a36Sopenharmony_ci	} else
241262306a36Sopenharmony_ci		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
241362306a36Sopenharmony_ci			 "0547 Unknown debugfs error injection entry\n");
241462306a36Sopenharmony_ci
241562306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, &cbuf, cnt);
241662306a36Sopenharmony_ci}
241762306a36Sopenharmony_ci
241862306a36Sopenharmony_cistatic ssize_t
241962306a36Sopenharmony_cilpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
242062306a36Sopenharmony_ci	size_t nbytes, loff_t *ppos)
242162306a36Sopenharmony_ci{
242262306a36Sopenharmony_ci	struct dentry *dent = file->f_path.dentry;
242362306a36Sopenharmony_ci	struct lpfc_hba *phba = file->private_data;
242462306a36Sopenharmony_ci	char dstbuf[33];
242562306a36Sopenharmony_ci	uint64_t tmp = 0;
242662306a36Sopenharmony_ci	int size;
242762306a36Sopenharmony_ci
242862306a36Sopenharmony_ci	memset(dstbuf, 0, 33);
242962306a36Sopenharmony_ci	size = (nbytes < 32) ? nbytes : 32;
243062306a36Sopenharmony_ci	if (copy_from_user(dstbuf, buf, size))
243162306a36Sopenharmony_ci		return -EFAULT;
243262306a36Sopenharmony_ci
243362306a36Sopenharmony_ci	if (dent == phba->debug_InjErrLBA) {
243462306a36Sopenharmony_ci		if ((dstbuf[0] == 'o') && (dstbuf[1] == 'f') &&
243562306a36Sopenharmony_ci		    (dstbuf[2] == 'f'))
243662306a36Sopenharmony_ci			tmp = (uint64_t)(-1);
243762306a36Sopenharmony_ci	}
243862306a36Sopenharmony_ci
243962306a36Sopenharmony_ci	if ((tmp == 0) && (kstrtoull(dstbuf, 0, &tmp)))
244062306a36Sopenharmony_ci		return -EINVAL;
244162306a36Sopenharmony_ci
244262306a36Sopenharmony_ci	if (dent == phba->debug_writeGuard)
244362306a36Sopenharmony_ci		phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp;
244462306a36Sopenharmony_ci	else if (dent == phba->debug_writeApp)
244562306a36Sopenharmony_ci		phba->lpfc_injerr_wapp_cnt = (uint32_t)tmp;
244662306a36Sopenharmony_ci	else if (dent == phba->debug_writeRef)
244762306a36Sopenharmony_ci		phba->lpfc_injerr_wref_cnt = (uint32_t)tmp;
244862306a36Sopenharmony_ci	else if (dent == phba->debug_readGuard)
244962306a36Sopenharmony_ci		phba->lpfc_injerr_rgrd_cnt = (uint32_t)tmp;
245062306a36Sopenharmony_ci	else if (dent == phba->debug_readApp)
245162306a36Sopenharmony_ci		phba->lpfc_injerr_rapp_cnt = (uint32_t)tmp;
245262306a36Sopenharmony_ci	else if (dent == phba->debug_readRef)
245362306a36Sopenharmony_ci		phba->lpfc_injerr_rref_cnt = (uint32_t)tmp;
245462306a36Sopenharmony_ci	else if (dent == phba->debug_InjErrLBA)
245562306a36Sopenharmony_ci		phba->lpfc_injerr_lba = (sector_t)tmp;
245662306a36Sopenharmony_ci	else if (dent == phba->debug_InjErrNPortID)
245762306a36Sopenharmony_ci		phba->lpfc_injerr_nportid = (uint32_t)(tmp & Mask_DID);
245862306a36Sopenharmony_ci	else if (dent == phba->debug_InjErrWWPN) {
245962306a36Sopenharmony_ci		tmp = cpu_to_be64(tmp);
246062306a36Sopenharmony_ci		memcpy(&phba->lpfc_injerr_wwpn, &tmp, sizeof(struct lpfc_name));
246162306a36Sopenharmony_ci	} else
246262306a36Sopenharmony_ci		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
246362306a36Sopenharmony_ci			 "0548 Unknown debugfs error injection entry\n");
246462306a36Sopenharmony_ci
246562306a36Sopenharmony_ci	return nbytes;
246662306a36Sopenharmony_ci}
246762306a36Sopenharmony_ci
246862306a36Sopenharmony_cistatic int
246962306a36Sopenharmony_cilpfc_debugfs_dif_err_release(struct inode *inode, struct file *file)
247062306a36Sopenharmony_ci{
247162306a36Sopenharmony_ci	return 0;
247262306a36Sopenharmony_ci}
247362306a36Sopenharmony_ci
247462306a36Sopenharmony_ci/**
247562306a36Sopenharmony_ci * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file
247662306a36Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer.
247762306a36Sopenharmony_ci * @file: The file pointer to attach the log output.
247862306a36Sopenharmony_ci *
247962306a36Sopenharmony_ci * Description:
248062306a36Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It gets
248162306a36Sopenharmony_ci * the vport from the i_private field in @inode, allocates the necessary buffer
248262306a36Sopenharmony_ci * for the log, fills the buffer from the in-memory log for this vport, and then
248362306a36Sopenharmony_ci * returns a pointer to that log in the private_data field in @file.
248462306a36Sopenharmony_ci *
248562306a36Sopenharmony_ci * Returns:
248662306a36Sopenharmony_ci * This function returns zero if successful. On error it will return a negative
248762306a36Sopenharmony_ci * error value.
248862306a36Sopenharmony_ci **/
248962306a36Sopenharmony_cistatic int
249062306a36Sopenharmony_cilpfc_debugfs_nodelist_open(struct inode *inode, struct file *file)
249162306a36Sopenharmony_ci{
249262306a36Sopenharmony_ci	struct lpfc_vport *vport = inode->i_private;
249362306a36Sopenharmony_ci	struct lpfc_debug *debug;
249462306a36Sopenharmony_ci	int rc = -ENOMEM;
249562306a36Sopenharmony_ci
249662306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
249762306a36Sopenharmony_ci	if (!debug)
249862306a36Sopenharmony_ci		goto out;
249962306a36Sopenharmony_ci
250062306a36Sopenharmony_ci	/* Round to page boundary */
250162306a36Sopenharmony_ci	debug->buffer = kmalloc(LPFC_NODELIST_SIZE, GFP_KERNEL);
250262306a36Sopenharmony_ci	if (!debug->buffer) {
250362306a36Sopenharmony_ci		kfree(debug);
250462306a36Sopenharmony_ci		goto out;
250562306a36Sopenharmony_ci	}
250662306a36Sopenharmony_ci
250762306a36Sopenharmony_ci	debug->len = lpfc_debugfs_nodelist_data(vport, debug->buffer,
250862306a36Sopenharmony_ci		LPFC_NODELIST_SIZE);
250962306a36Sopenharmony_ci	file->private_data = debug;
251062306a36Sopenharmony_ci
251162306a36Sopenharmony_ci	rc = 0;
251262306a36Sopenharmony_ciout:
251362306a36Sopenharmony_ci	return rc;
251462306a36Sopenharmony_ci}
251562306a36Sopenharmony_ci
251662306a36Sopenharmony_ci/**
251762306a36Sopenharmony_ci * lpfc_debugfs_lseek - Seek through a debugfs file
251862306a36Sopenharmony_ci * @file: The file pointer to seek through.
251962306a36Sopenharmony_ci * @off: The offset to seek to or the amount to seek by.
252062306a36Sopenharmony_ci * @whence: Indicates how to seek.
252162306a36Sopenharmony_ci *
252262306a36Sopenharmony_ci * Description:
252362306a36Sopenharmony_ci * This routine is the entry point for the debugfs lseek file operation. The
252462306a36Sopenharmony_ci * @whence parameter indicates whether @off is the offset to directly seek to,
252562306a36Sopenharmony_ci * or if it is a value to seek forward or reverse by. This function figures out
252662306a36Sopenharmony_ci * what the new offset of the debugfs file will be and assigns that value to the
252762306a36Sopenharmony_ci * f_pos field of @file.
252862306a36Sopenharmony_ci *
252962306a36Sopenharmony_ci * Returns:
253062306a36Sopenharmony_ci * This function returns the new offset if successful and returns a negative
253162306a36Sopenharmony_ci * error if unable to process the seek.
253262306a36Sopenharmony_ci **/
253362306a36Sopenharmony_cistatic loff_t
253462306a36Sopenharmony_cilpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
253562306a36Sopenharmony_ci{
253662306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
253762306a36Sopenharmony_ci	return fixed_size_llseek(file, off, whence, debug->len);
253862306a36Sopenharmony_ci}
253962306a36Sopenharmony_ci
254062306a36Sopenharmony_ci/**
254162306a36Sopenharmony_ci * lpfc_debugfs_read - Read a debugfs file
254262306a36Sopenharmony_ci * @file: The file pointer to read from.
254362306a36Sopenharmony_ci * @buf: The buffer to copy the data to.
254462306a36Sopenharmony_ci * @nbytes: The number of bytes to read.
254562306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
254662306a36Sopenharmony_ci *
254762306a36Sopenharmony_ci * Description:
254862306a36Sopenharmony_ci * This routine reads data from from the buffer indicated in the private_data
254962306a36Sopenharmony_ci * field of @file. It will start reading at @ppos and copy up to @nbytes of
255062306a36Sopenharmony_ci * data to @buf.
255162306a36Sopenharmony_ci *
255262306a36Sopenharmony_ci * Returns:
255362306a36Sopenharmony_ci * This function returns the amount of data that was read (this could be less
255462306a36Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value.
255562306a36Sopenharmony_ci **/
255662306a36Sopenharmony_cistatic ssize_t
255762306a36Sopenharmony_cilpfc_debugfs_read(struct file *file, char __user *buf,
255862306a36Sopenharmony_ci		  size_t nbytes, loff_t *ppos)
255962306a36Sopenharmony_ci{
256062306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
256162306a36Sopenharmony_ci
256262306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer,
256362306a36Sopenharmony_ci				       debug->len);
256462306a36Sopenharmony_ci}
256562306a36Sopenharmony_ci
256662306a36Sopenharmony_ci/**
256762306a36Sopenharmony_ci * lpfc_debugfs_release - Release the buffer used to store debugfs file data
256862306a36Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer. (unused)
256962306a36Sopenharmony_ci * @file: The file pointer that contains the buffer to release.
257062306a36Sopenharmony_ci *
257162306a36Sopenharmony_ci * Description:
257262306a36Sopenharmony_ci * This routine frees the buffer that was allocated when the debugfs file was
257362306a36Sopenharmony_ci * opened.
257462306a36Sopenharmony_ci *
257562306a36Sopenharmony_ci * Returns:
257662306a36Sopenharmony_ci * This function returns zero.
257762306a36Sopenharmony_ci **/
257862306a36Sopenharmony_cistatic int
257962306a36Sopenharmony_cilpfc_debugfs_release(struct inode *inode, struct file *file)
258062306a36Sopenharmony_ci{
258162306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
258262306a36Sopenharmony_ci
258362306a36Sopenharmony_ci	kfree(debug->buffer);
258462306a36Sopenharmony_ci	kfree(debug);
258562306a36Sopenharmony_ci
258662306a36Sopenharmony_ci	return 0;
258762306a36Sopenharmony_ci}
258862306a36Sopenharmony_ci
258962306a36Sopenharmony_ci/**
259062306a36Sopenharmony_ci * lpfc_debugfs_multixripools_write - Clear multi-XRI pools statistics
259162306a36Sopenharmony_ci * @file: The file pointer to read from.
259262306a36Sopenharmony_ci * @buf: The buffer to copy the user data from.
259362306a36Sopenharmony_ci * @nbytes: The number of bytes to get.
259462306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
259562306a36Sopenharmony_ci *
259662306a36Sopenharmony_ci * Description:
259762306a36Sopenharmony_ci * This routine clears multi-XRI pools statistics when buf contains "clear".
259862306a36Sopenharmony_ci *
259962306a36Sopenharmony_ci * Return Value:
260062306a36Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful.
260162306a36Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user
260262306a36Sopenharmony_ci * space.
260362306a36Sopenharmony_ci **/
260462306a36Sopenharmony_cistatic ssize_t
260562306a36Sopenharmony_cilpfc_debugfs_multixripools_write(struct file *file, const char __user *buf,
260662306a36Sopenharmony_ci				 size_t nbytes, loff_t *ppos)
260762306a36Sopenharmony_ci{
260862306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
260962306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
261062306a36Sopenharmony_ci	char mybuf[64];
261162306a36Sopenharmony_ci	char *pbuf;
261262306a36Sopenharmony_ci	u32 i;
261362306a36Sopenharmony_ci	u32 hwq_count;
261462306a36Sopenharmony_ci	struct lpfc_sli4_hdw_queue *qp;
261562306a36Sopenharmony_ci	struct lpfc_multixri_pool *multixri_pool;
261662306a36Sopenharmony_ci
261762306a36Sopenharmony_ci	if (nbytes > sizeof(mybuf) - 1)
261862306a36Sopenharmony_ci		nbytes = sizeof(mybuf) - 1;
261962306a36Sopenharmony_ci
262062306a36Sopenharmony_ci	memset(mybuf, 0, sizeof(mybuf));
262162306a36Sopenharmony_ci
262262306a36Sopenharmony_ci	if (copy_from_user(mybuf, buf, nbytes))
262362306a36Sopenharmony_ci		return -EFAULT;
262462306a36Sopenharmony_ci	pbuf = &mybuf[0];
262562306a36Sopenharmony_ci
262662306a36Sopenharmony_ci	if ((strncmp(pbuf, "clear", strlen("clear"))) == 0) {
262762306a36Sopenharmony_ci		hwq_count = phba->cfg_hdw_queue;
262862306a36Sopenharmony_ci		for (i = 0; i < hwq_count; i++) {
262962306a36Sopenharmony_ci			qp = &phba->sli4_hba.hdwq[i];
263062306a36Sopenharmony_ci			multixri_pool = qp->p_multixri_pool;
263162306a36Sopenharmony_ci			if (!multixri_pool)
263262306a36Sopenharmony_ci				continue;
263362306a36Sopenharmony_ci
263462306a36Sopenharmony_ci			qp->empty_io_bufs = 0;
263562306a36Sopenharmony_ci			multixri_pool->pbl_empty_count = 0;
263662306a36Sopenharmony_ci#ifdef LPFC_MXP_STAT
263762306a36Sopenharmony_ci			multixri_pool->above_limit_count = 0;
263862306a36Sopenharmony_ci			multixri_pool->below_limit_count = 0;
263962306a36Sopenharmony_ci			multixri_pool->stat_max_hwm = 0;
264062306a36Sopenharmony_ci			multixri_pool->local_pbl_hit_count = 0;
264162306a36Sopenharmony_ci			multixri_pool->other_pbl_hit_count = 0;
264262306a36Sopenharmony_ci
264362306a36Sopenharmony_ci			multixri_pool->stat_pbl_count = 0;
264462306a36Sopenharmony_ci			multixri_pool->stat_pvt_count = 0;
264562306a36Sopenharmony_ci			multixri_pool->stat_busy_count = 0;
264662306a36Sopenharmony_ci			multixri_pool->stat_snapshot_taken = 0;
264762306a36Sopenharmony_ci#endif
264862306a36Sopenharmony_ci		}
264962306a36Sopenharmony_ci		return strlen(pbuf);
265062306a36Sopenharmony_ci	}
265162306a36Sopenharmony_ci
265262306a36Sopenharmony_ci	return -EINVAL;
265362306a36Sopenharmony_ci}
265462306a36Sopenharmony_ci
265562306a36Sopenharmony_cistatic int
265662306a36Sopenharmony_cilpfc_debugfs_nvmestat_open(struct inode *inode, struct file *file)
265762306a36Sopenharmony_ci{
265862306a36Sopenharmony_ci	struct lpfc_vport *vport = inode->i_private;
265962306a36Sopenharmony_ci	struct lpfc_debug *debug;
266062306a36Sopenharmony_ci	int rc = -ENOMEM;
266162306a36Sopenharmony_ci
266262306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
266362306a36Sopenharmony_ci	if (!debug)
266462306a36Sopenharmony_ci		goto out;
266562306a36Sopenharmony_ci
266662306a36Sopenharmony_ci	 /* Round to page boundary */
266762306a36Sopenharmony_ci	debug->buffer = kmalloc(LPFC_NVMESTAT_SIZE, GFP_KERNEL);
266862306a36Sopenharmony_ci	if (!debug->buffer) {
266962306a36Sopenharmony_ci		kfree(debug);
267062306a36Sopenharmony_ci		goto out;
267162306a36Sopenharmony_ci	}
267262306a36Sopenharmony_ci
267362306a36Sopenharmony_ci	debug->len = lpfc_debugfs_nvmestat_data(vport, debug->buffer,
267462306a36Sopenharmony_ci		LPFC_NVMESTAT_SIZE);
267562306a36Sopenharmony_ci
267662306a36Sopenharmony_ci	debug->i_private = inode->i_private;
267762306a36Sopenharmony_ci	file->private_data = debug;
267862306a36Sopenharmony_ci
267962306a36Sopenharmony_ci	rc = 0;
268062306a36Sopenharmony_ciout:
268162306a36Sopenharmony_ci	return rc;
268262306a36Sopenharmony_ci}
268362306a36Sopenharmony_ci
268462306a36Sopenharmony_cistatic ssize_t
268562306a36Sopenharmony_cilpfc_debugfs_nvmestat_write(struct file *file, const char __user *buf,
268662306a36Sopenharmony_ci			    size_t nbytes, loff_t *ppos)
268762306a36Sopenharmony_ci{
268862306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
268962306a36Sopenharmony_ci	struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private;
269062306a36Sopenharmony_ci	struct lpfc_hba   *phba = vport->phba;
269162306a36Sopenharmony_ci	struct lpfc_nvmet_tgtport *tgtp;
269262306a36Sopenharmony_ci	char mybuf[64];
269362306a36Sopenharmony_ci	char *pbuf;
269462306a36Sopenharmony_ci
269562306a36Sopenharmony_ci	if (!phba->targetport)
269662306a36Sopenharmony_ci		return -ENXIO;
269762306a36Sopenharmony_ci
269862306a36Sopenharmony_ci	if (nbytes > sizeof(mybuf) - 1)
269962306a36Sopenharmony_ci		nbytes = sizeof(mybuf) - 1;
270062306a36Sopenharmony_ci
270162306a36Sopenharmony_ci	memset(mybuf, 0, sizeof(mybuf));
270262306a36Sopenharmony_ci
270362306a36Sopenharmony_ci	if (copy_from_user(mybuf, buf, nbytes))
270462306a36Sopenharmony_ci		return -EFAULT;
270562306a36Sopenharmony_ci	pbuf = &mybuf[0];
270662306a36Sopenharmony_ci
270762306a36Sopenharmony_ci	tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
270862306a36Sopenharmony_ci	if ((strncmp(pbuf, "reset", strlen("reset")) == 0) ||
270962306a36Sopenharmony_ci	    (strncmp(pbuf, "zero", strlen("zero")) == 0)) {
271062306a36Sopenharmony_ci		atomic_set(&tgtp->rcv_ls_req_in, 0);
271162306a36Sopenharmony_ci		atomic_set(&tgtp->rcv_ls_req_out, 0);
271262306a36Sopenharmony_ci		atomic_set(&tgtp->rcv_ls_req_drop, 0);
271362306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_ls_abort, 0);
271462306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_ls_abort_cmpl, 0);
271562306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_ls_rsp, 0);
271662306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_ls_drop, 0);
271762306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_ls_rsp_error, 0);
271862306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_ls_rsp_cmpl, 0);
271962306a36Sopenharmony_ci
272062306a36Sopenharmony_ci		atomic_set(&tgtp->rcv_fcp_cmd_in, 0);
272162306a36Sopenharmony_ci		atomic_set(&tgtp->rcv_fcp_cmd_out, 0);
272262306a36Sopenharmony_ci		atomic_set(&tgtp->rcv_fcp_cmd_drop, 0);
272362306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_fcp_drop, 0);
272462306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_fcp_read_rsp, 0);
272562306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_fcp_read, 0);
272662306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_fcp_write, 0);
272762306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_fcp_rsp, 0);
272862306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_fcp_release, 0);
272962306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_fcp_rsp_cmpl, 0);
273062306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_fcp_rsp_error, 0);
273162306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_fcp_rsp_drop, 0);
273262306a36Sopenharmony_ci
273362306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_fcp_abort, 0);
273462306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_fcp_abort_cmpl, 0);
273562306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_abort_sol, 0);
273662306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_abort_unsol, 0);
273762306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_abort_rsp, 0);
273862306a36Sopenharmony_ci		atomic_set(&tgtp->xmt_abort_rsp_error, 0);
273962306a36Sopenharmony_ci	}
274062306a36Sopenharmony_ci	return nbytes;
274162306a36Sopenharmony_ci}
274262306a36Sopenharmony_ci
274362306a36Sopenharmony_cistatic int
274462306a36Sopenharmony_cilpfc_debugfs_scsistat_open(struct inode *inode, struct file *file)
274562306a36Sopenharmony_ci{
274662306a36Sopenharmony_ci	struct lpfc_vport *vport = inode->i_private;
274762306a36Sopenharmony_ci	struct lpfc_debug *debug;
274862306a36Sopenharmony_ci	int rc = -ENOMEM;
274962306a36Sopenharmony_ci
275062306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
275162306a36Sopenharmony_ci	if (!debug)
275262306a36Sopenharmony_ci		goto out;
275362306a36Sopenharmony_ci
275462306a36Sopenharmony_ci	 /* Round to page boundary */
275562306a36Sopenharmony_ci	debug->buffer = kzalloc(LPFC_SCSISTAT_SIZE, GFP_KERNEL);
275662306a36Sopenharmony_ci	if (!debug->buffer) {
275762306a36Sopenharmony_ci		kfree(debug);
275862306a36Sopenharmony_ci		goto out;
275962306a36Sopenharmony_ci	}
276062306a36Sopenharmony_ci
276162306a36Sopenharmony_ci	debug->len = lpfc_debugfs_scsistat_data(vport, debug->buffer,
276262306a36Sopenharmony_ci		LPFC_SCSISTAT_SIZE);
276362306a36Sopenharmony_ci
276462306a36Sopenharmony_ci	debug->i_private = inode->i_private;
276562306a36Sopenharmony_ci	file->private_data = debug;
276662306a36Sopenharmony_ci
276762306a36Sopenharmony_ci	rc = 0;
276862306a36Sopenharmony_ciout:
276962306a36Sopenharmony_ci	return rc;
277062306a36Sopenharmony_ci}
277162306a36Sopenharmony_ci
277262306a36Sopenharmony_cistatic ssize_t
277362306a36Sopenharmony_cilpfc_debugfs_scsistat_write(struct file *file, const char __user *buf,
277462306a36Sopenharmony_ci			    size_t nbytes, loff_t *ppos)
277562306a36Sopenharmony_ci{
277662306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
277762306a36Sopenharmony_ci	struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private;
277862306a36Sopenharmony_ci	struct lpfc_hba *phba = vport->phba;
277962306a36Sopenharmony_ci	char mybuf[6] = {0};
278062306a36Sopenharmony_ci	int i;
278162306a36Sopenharmony_ci
278262306a36Sopenharmony_ci	if (copy_from_user(mybuf, buf, (nbytes >= sizeof(mybuf)) ?
278362306a36Sopenharmony_ci				       (sizeof(mybuf) - 1) : nbytes))
278462306a36Sopenharmony_ci		return -EFAULT;
278562306a36Sopenharmony_ci
278662306a36Sopenharmony_ci	if ((strncmp(&mybuf[0], "reset", strlen("reset")) == 0) ||
278762306a36Sopenharmony_ci	    (strncmp(&mybuf[0], "zero", strlen("zero")) == 0)) {
278862306a36Sopenharmony_ci		for (i = 0; i < phba->cfg_hdw_queue; i++) {
278962306a36Sopenharmony_ci			memset(&phba->sli4_hba.hdwq[i].scsi_cstat, 0,
279062306a36Sopenharmony_ci			       sizeof(phba->sli4_hba.hdwq[i].scsi_cstat));
279162306a36Sopenharmony_ci		}
279262306a36Sopenharmony_ci	}
279362306a36Sopenharmony_ci
279462306a36Sopenharmony_ci	return nbytes;
279562306a36Sopenharmony_ci}
279662306a36Sopenharmony_ci
279762306a36Sopenharmony_cistatic int
279862306a36Sopenharmony_cilpfc_debugfs_ioktime_open(struct inode *inode, struct file *file)
279962306a36Sopenharmony_ci{
280062306a36Sopenharmony_ci	struct lpfc_vport *vport = inode->i_private;
280162306a36Sopenharmony_ci	struct lpfc_debug *debug;
280262306a36Sopenharmony_ci	int rc = -ENOMEM;
280362306a36Sopenharmony_ci
280462306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
280562306a36Sopenharmony_ci	if (!debug)
280662306a36Sopenharmony_ci		goto out;
280762306a36Sopenharmony_ci
280862306a36Sopenharmony_ci	 /* Round to page boundary */
280962306a36Sopenharmony_ci	debug->buffer = kmalloc(LPFC_IOKTIME_SIZE, GFP_KERNEL);
281062306a36Sopenharmony_ci	if (!debug->buffer) {
281162306a36Sopenharmony_ci		kfree(debug);
281262306a36Sopenharmony_ci		goto out;
281362306a36Sopenharmony_ci	}
281462306a36Sopenharmony_ci
281562306a36Sopenharmony_ci	debug->len = lpfc_debugfs_ioktime_data(vport, debug->buffer,
281662306a36Sopenharmony_ci		LPFC_IOKTIME_SIZE);
281762306a36Sopenharmony_ci
281862306a36Sopenharmony_ci	debug->i_private = inode->i_private;
281962306a36Sopenharmony_ci	file->private_data = debug;
282062306a36Sopenharmony_ci
282162306a36Sopenharmony_ci	rc = 0;
282262306a36Sopenharmony_ciout:
282362306a36Sopenharmony_ci	return rc;
282462306a36Sopenharmony_ci}
282562306a36Sopenharmony_ci
282662306a36Sopenharmony_cistatic ssize_t
282762306a36Sopenharmony_cilpfc_debugfs_ioktime_write(struct file *file, const char __user *buf,
282862306a36Sopenharmony_ci			   size_t nbytes, loff_t *ppos)
282962306a36Sopenharmony_ci{
283062306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
283162306a36Sopenharmony_ci	struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private;
283262306a36Sopenharmony_ci	struct lpfc_hba   *phba = vport->phba;
283362306a36Sopenharmony_ci	char mybuf[64];
283462306a36Sopenharmony_ci	char *pbuf;
283562306a36Sopenharmony_ci
283662306a36Sopenharmony_ci	if (nbytes > sizeof(mybuf) - 1)
283762306a36Sopenharmony_ci		nbytes = sizeof(mybuf) - 1;
283862306a36Sopenharmony_ci
283962306a36Sopenharmony_ci	memset(mybuf, 0, sizeof(mybuf));
284062306a36Sopenharmony_ci
284162306a36Sopenharmony_ci	if (copy_from_user(mybuf, buf, nbytes))
284262306a36Sopenharmony_ci		return -EFAULT;
284362306a36Sopenharmony_ci	pbuf = &mybuf[0];
284462306a36Sopenharmony_ci
284562306a36Sopenharmony_ci	if ((strncmp(pbuf, "on", sizeof("on") - 1) == 0)) {
284662306a36Sopenharmony_ci		phba->ktime_data_samples = 0;
284762306a36Sopenharmony_ci		phba->ktime_status_samples = 0;
284862306a36Sopenharmony_ci		phba->ktime_seg1_total = 0;
284962306a36Sopenharmony_ci		phba->ktime_seg1_max = 0;
285062306a36Sopenharmony_ci		phba->ktime_seg1_min = 0xffffffff;
285162306a36Sopenharmony_ci		phba->ktime_seg2_total = 0;
285262306a36Sopenharmony_ci		phba->ktime_seg2_max = 0;
285362306a36Sopenharmony_ci		phba->ktime_seg2_min = 0xffffffff;
285462306a36Sopenharmony_ci		phba->ktime_seg3_total = 0;
285562306a36Sopenharmony_ci		phba->ktime_seg3_max = 0;
285662306a36Sopenharmony_ci		phba->ktime_seg3_min = 0xffffffff;
285762306a36Sopenharmony_ci		phba->ktime_seg4_total = 0;
285862306a36Sopenharmony_ci		phba->ktime_seg4_max = 0;
285962306a36Sopenharmony_ci		phba->ktime_seg4_min = 0xffffffff;
286062306a36Sopenharmony_ci		phba->ktime_seg5_total = 0;
286162306a36Sopenharmony_ci		phba->ktime_seg5_max = 0;
286262306a36Sopenharmony_ci		phba->ktime_seg5_min = 0xffffffff;
286362306a36Sopenharmony_ci		phba->ktime_seg6_total = 0;
286462306a36Sopenharmony_ci		phba->ktime_seg6_max = 0;
286562306a36Sopenharmony_ci		phba->ktime_seg6_min = 0xffffffff;
286662306a36Sopenharmony_ci		phba->ktime_seg7_total = 0;
286762306a36Sopenharmony_ci		phba->ktime_seg7_max = 0;
286862306a36Sopenharmony_ci		phba->ktime_seg7_min = 0xffffffff;
286962306a36Sopenharmony_ci		phba->ktime_seg8_total = 0;
287062306a36Sopenharmony_ci		phba->ktime_seg8_max = 0;
287162306a36Sopenharmony_ci		phba->ktime_seg8_min = 0xffffffff;
287262306a36Sopenharmony_ci		phba->ktime_seg9_total = 0;
287362306a36Sopenharmony_ci		phba->ktime_seg9_max = 0;
287462306a36Sopenharmony_ci		phba->ktime_seg9_min = 0xffffffff;
287562306a36Sopenharmony_ci		phba->ktime_seg10_total = 0;
287662306a36Sopenharmony_ci		phba->ktime_seg10_max = 0;
287762306a36Sopenharmony_ci		phba->ktime_seg10_min = 0xffffffff;
287862306a36Sopenharmony_ci
287962306a36Sopenharmony_ci		phba->ktime_on = 1;
288062306a36Sopenharmony_ci		return strlen(pbuf);
288162306a36Sopenharmony_ci	} else if ((strncmp(pbuf, "off",
288262306a36Sopenharmony_ci		   sizeof("off") - 1) == 0)) {
288362306a36Sopenharmony_ci		phba->ktime_on = 0;
288462306a36Sopenharmony_ci		return strlen(pbuf);
288562306a36Sopenharmony_ci	} else if ((strncmp(pbuf, "zero",
288662306a36Sopenharmony_ci		   sizeof("zero") - 1) == 0)) {
288762306a36Sopenharmony_ci		phba->ktime_data_samples = 0;
288862306a36Sopenharmony_ci		phba->ktime_status_samples = 0;
288962306a36Sopenharmony_ci		phba->ktime_seg1_total = 0;
289062306a36Sopenharmony_ci		phba->ktime_seg1_max = 0;
289162306a36Sopenharmony_ci		phba->ktime_seg1_min = 0xffffffff;
289262306a36Sopenharmony_ci		phba->ktime_seg2_total = 0;
289362306a36Sopenharmony_ci		phba->ktime_seg2_max = 0;
289462306a36Sopenharmony_ci		phba->ktime_seg2_min = 0xffffffff;
289562306a36Sopenharmony_ci		phba->ktime_seg3_total = 0;
289662306a36Sopenharmony_ci		phba->ktime_seg3_max = 0;
289762306a36Sopenharmony_ci		phba->ktime_seg3_min = 0xffffffff;
289862306a36Sopenharmony_ci		phba->ktime_seg4_total = 0;
289962306a36Sopenharmony_ci		phba->ktime_seg4_max = 0;
290062306a36Sopenharmony_ci		phba->ktime_seg4_min = 0xffffffff;
290162306a36Sopenharmony_ci		phba->ktime_seg5_total = 0;
290262306a36Sopenharmony_ci		phba->ktime_seg5_max = 0;
290362306a36Sopenharmony_ci		phba->ktime_seg5_min = 0xffffffff;
290462306a36Sopenharmony_ci		phba->ktime_seg6_total = 0;
290562306a36Sopenharmony_ci		phba->ktime_seg6_max = 0;
290662306a36Sopenharmony_ci		phba->ktime_seg6_min = 0xffffffff;
290762306a36Sopenharmony_ci		phba->ktime_seg7_total = 0;
290862306a36Sopenharmony_ci		phba->ktime_seg7_max = 0;
290962306a36Sopenharmony_ci		phba->ktime_seg7_min = 0xffffffff;
291062306a36Sopenharmony_ci		phba->ktime_seg8_total = 0;
291162306a36Sopenharmony_ci		phba->ktime_seg8_max = 0;
291262306a36Sopenharmony_ci		phba->ktime_seg8_min = 0xffffffff;
291362306a36Sopenharmony_ci		phba->ktime_seg9_total = 0;
291462306a36Sopenharmony_ci		phba->ktime_seg9_max = 0;
291562306a36Sopenharmony_ci		phba->ktime_seg9_min = 0xffffffff;
291662306a36Sopenharmony_ci		phba->ktime_seg10_total = 0;
291762306a36Sopenharmony_ci		phba->ktime_seg10_max = 0;
291862306a36Sopenharmony_ci		phba->ktime_seg10_min = 0xffffffff;
291962306a36Sopenharmony_ci		return strlen(pbuf);
292062306a36Sopenharmony_ci	}
292162306a36Sopenharmony_ci	return -EINVAL;
292262306a36Sopenharmony_ci}
292362306a36Sopenharmony_ci
292462306a36Sopenharmony_cistatic int
292562306a36Sopenharmony_cilpfc_debugfs_nvmeio_trc_open(struct inode *inode, struct file *file)
292662306a36Sopenharmony_ci{
292762306a36Sopenharmony_ci	struct lpfc_hba *phba = inode->i_private;
292862306a36Sopenharmony_ci	struct lpfc_debug *debug;
292962306a36Sopenharmony_ci	int rc = -ENOMEM;
293062306a36Sopenharmony_ci
293162306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
293262306a36Sopenharmony_ci	if (!debug)
293362306a36Sopenharmony_ci		goto out;
293462306a36Sopenharmony_ci
293562306a36Sopenharmony_ci	 /* Round to page boundary */
293662306a36Sopenharmony_ci	debug->buffer = kmalloc(LPFC_NVMEIO_TRC_SIZE, GFP_KERNEL);
293762306a36Sopenharmony_ci	if (!debug->buffer) {
293862306a36Sopenharmony_ci		kfree(debug);
293962306a36Sopenharmony_ci		goto out;
294062306a36Sopenharmony_ci	}
294162306a36Sopenharmony_ci
294262306a36Sopenharmony_ci	debug->len = lpfc_debugfs_nvmeio_trc_data(phba, debug->buffer,
294362306a36Sopenharmony_ci		LPFC_NVMEIO_TRC_SIZE);
294462306a36Sopenharmony_ci
294562306a36Sopenharmony_ci	debug->i_private = inode->i_private;
294662306a36Sopenharmony_ci	file->private_data = debug;
294762306a36Sopenharmony_ci
294862306a36Sopenharmony_ci	rc = 0;
294962306a36Sopenharmony_ciout:
295062306a36Sopenharmony_ci	return rc;
295162306a36Sopenharmony_ci}
295262306a36Sopenharmony_ci
295362306a36Sopenharmony_cistatic ssize_t
295462306a36Sopenharmony_cilpfc_debugfs_nvmeio_trc_write(struct file *file, const char __user *buf,
295562306a36Sopenharmony_ci			      size_t nbytes, loff_t *ppos)
295662306a36Sopenharmony_ci{
295762306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
295862306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
295962306a36Sopenharmony_ci	int i;
296062306a36Sopenharmony_ci	unsigned long sz;
296162306a36Sopenharmony_ci	char mybuf[64];
296262306a36Sopenharmony_ci	char *pbuf;
296362306a36Sopenharmony_ci
296462306a36Sopenharmony_ci	if (nbytes > sizeof(mybuf) - 1)
296562306a36Sopenharmony_ci		nbytes = sizeof(mybuf) - 1;
296662306a36Sopenharmony_ci
296762306a36Sopenharmony_ci	memset(mybuf, 0, sizeof(mybuf));
296862306a36Sopenharmony_ci
296962306a36Sopenharmony_ci	if (copy_from_user(mybuf, buf, nbytes))
297062306a36Sopenharmony_ci		return -EFAULT;
297162306a36Sopenharmony_ci	pbuf = &mybuf[0];
297262306a36Sopenharmony_ci
297362306a36Sopenharmony_ci	if ((strncmp(pbuf, "off", sizeof("off") - 1) == 0)) {
297462306a36Sopenharmony_ci		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
297562306a36Sopenharmony_ci				"0570 nvmeio_trc_off\n");
297662306a36Sopenharmony_ci		phba->nvmeio_trc_output_idx = 0;
297762306a36Sopenharmony_ci		phba->nvmeio_trc_on = 0;
297862306a36Sopenharmony_ci		return strlen(pbuf);
297962306a36Sopenharmony_ci	} else if ((strncmp(pbuf, "on", sizeof("on") - 1) == 0)) {
298062306a36Sopenharmony_ci		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
298162306a36Sopenharmony_ci				"0571 nvmeio_trc_on\n");
298262306a36Sopenharmony_ci		phba->nvmeio_trc_output_idx = 0;
298362306a36Sopenharmony_ci		phba->nvmeio_trc_on = 1;
298462306a36Sopenharmony_ci		return strlen(pbuf);
298562306a36Sopenharmony_ci	}
298662306a36Sopenharmony_ci
298762306a36Sopenharmony_ci	/* We must be off to allocate the trace buffer */
298862306a36Sopenharmony_ci	if (phba->nvmeio_trc_on != 0)
298962306a36Sopenharmony_ci		return -EINVAL;
299062306a36Sopenharmony_ci
299162306a36Sopenharmony_ci	/* If not on or off, the parameter is the trace buffer size */
299262306a36Sopenharmony_ci	i = kstrtoul(pbuf, 0, &sz);
299362306a36Sopenharmony_ci	if (i)
299462306a36Sopenharmony_ci		return -EINVAL;
299562306a36Sopenharmony_ci	phba->nvmeio_trc_size = (uint32_t)sz;
299662306a36Sopenharmony_ci
299762306a36Sopenharmony_ci	/* It must be a power of 2 - round down */
299862306a36Sopenharmony_ci	i = 0;
299962306a36Sopenharmony_ci	while (sz > 1) {
300062306a36Sopenharmony_ci		sz = sz >> 1;
300162306a36Sopenharmony_ci		i++;
300262306a36Sopenharmony_ci	}
300362306a36Sopenharmony_ci	sz = (1 << i);
300462306a36Sopenharmony_ci	if (phba->nvmeio_trc_size != sz)
300562306a36Sopenharmony_ci		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
300662306a36Sopenharmony_ci				"0572 nvmeio_trc_size changed to %ld\n",
300762306a36Sopenharmony_ci				sz);
300862306a36Sopenharmony_ci	phba->nvmeio_trc_size = (uint32_t)sz;
300962306a36Sopenharmony_ci
301062306a36Sopenharmony_ci	/* If one previously exists, free it */
301162306a36Sopenharmony_ci	kfree(phba->nvmeio_trc);
301262306a36Sopenharmony_ci
301362306a36Sopenharmony_ci	/* Allocate new trace buffer and initialize */
301462306a36Sopenharmony_ci	phba->nvmeio_trc = kzalloc((sizeof(struct lpfc_debugfs_nvmeio_trc) *
301562306a36Sopenharmony_ci				    sz), GFP_KERNEL);
301662306a36Sopenharmony_ci	if (!phba->nvmeio_trc) {
301762306a36Sopenharmony_ci		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
301862306a36Sopenharmony_ci				"0573 Cannot create debugfs "
301962306a36Sopenharmony_ci				"nvmeio_trc buffer\n");
302062306a36Sopenharmony_ci		return -ENOMEM;
302162306a36Sopenharmony_ci	}
302262306a36Sopenharmony_ci	atomic_set(&phba->nvmeio_trc_cnt, 0);
302362306a36Sopenharmony_ci	phba->nvmeio_trc_on = 0;
302462306a36Sopenharmony_ci	phba->nvmeio_trc_output_idx = 0;
302562306a36Sopenharmony_ci
302662306a36Sopenharmony_ci	return strlen(pbuf);
302762306a36Sopenharmony_ci}
302862306a36Sopenharmony_ci
302962306a36Sopenharmony_cistatic int
303062306a36Sopenharmony_cilpfc_debugfs_hdwqstat_open(struct inode *inode, struct file *file)
303162306a36Sopenharmony_ci{
303262306a36Sopenharmony_ci	struct lpfc_vport *vport = inode->i_private;
303362306a36Sopenharmony_ci	struct lpfc_debug *debug;
303462306a36Sopenharmony_ci	int rc = -ENOMEM;
303562306a36Sopenharmony_ci
303662306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
303762306a36Sopenharmony_ci	if (!debug)
303862306a36Sopenharmony_ci		goto out;
303962306a36Sopenharmony_ci
304062306a36Sopenharmony_ci	 /* Round to page boundary */
304162306a36Sopenharmony_ci	debug->buffer = kcalloc(1, LPFC_SCSISTAT_SIZE, GFP_KERNEL);
304262306a36Sopenharmony_ci	if (!debug->buffer) {
304362306a36Sopenharmony_ci		kfree(debug);
304462306a36Sopenharmony_ci		goto out;
304562306a36Sopenharmony_ci	}
304662306a36Sopenharmony_ci
304762306a36Sopenharmony_ci	debug->len = lpfc_debugfs_hdwqstat_data(vport, debug->buffer,
304862306a36Sopenharmony_ci						LPFC_SCSISTAT_SIZE);
304962306a36Sopenharmony_ci
305062306a36Sopenharmony_ci	debug->i_private = inode->i_private;
305162306a36Sopenharmony_ci	file->private_data = debug;
305262306a36Sopenharmony_ci
305362306a36Sopenharmony_ci	rc = 0;
305462306a36Sopenharmony_ciout:
305562306a36Sopenharmony_ci	return rc;
305662306a36Sopenharmony_ci}
305762306a36Sopenharmony_ci
305862306a36Sopenharmony_cistatic ssize_t
305962306a36Sopenharmony_cilpfc_debugfs_hdwqstat_write(struct file *file, const char __user *buf,
306062306a36Sopenharmony_ci			    size_t nbytes, loff_t *ppos)
306162306a36Sopenharmony_ci{
306262306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
306362306a36Sopenharmony_ci	struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private;
306462306a36Sopenharmony_ci	struct lpfc_hba   *phba = vport->phba;
306562306a36Sopenharmony_ci	struct lpfc_hdwq_stat *c_stat;
306662306a36Sopenharmony_ci	char mybuf[64];
306762306a36Sopenharmony_ci	char *pbuf;
306862306a36Sopenharmony_ci	int i;
306962306a36Sopenharmony_ci
307062306a36Sopenharmony_ci	if (nbytes > sizeof(mybuf) - 1)
307162306a36Sopenharmony_ci		nbytes = sizeof(mybuf) - 1;
307262306a36Sopenharmony_ci
307362306a36Sopenharmony_ci	memset(mybuf, 0, sizeof(mybuf));
307462306a36Sopenharmony_ci
307562306a36Sopenharmony_ci	if (copy_from_user(mybuf, buf, nbytes))
307662306a36Sopenharmony_ci		return -EFAULT;
307762306a36Sopenharmony_ci	pbuf = &mybuf[0];
307862306a36Sopenharmony_ci
307962306a36Sopenharmony_ci	if ((strncmp(pbuf, "on", sizeof("on") - 1) == 0)) {
308062306a36Sopenharmony_ci		if (phba->nvmet_support)
308162306a36Sopenharmony_ci			phba->hdwqstat_on |= LPFC_CHECK_NVMET_IO;
308262306a36Sopenharmony_ci		else
308362306a36Sopenharmony_ci			phba->hdwqstat_on |= (LPFC_CHECK_NVME_IO |
308462306a36Sopenharmony_ci				LPFC_CHECK_SCSI_IO);
308562306a36Sopenharmony_ci		return strlen(pbuf);
308662306a36Sopenharmony_ci	} else if ((strncmp(pbuf, "nvme_on", sizeof("nvme_on") - 1) == 0)) {
308762306a36Sopenharmony_ci		if (phba->nvmet_support)
308862306a36Sopenharmony_ci			phba->hdwqstat_on |= LPFC_CHECK_NVMET_IO;
308962306a36Sopenharmony_ci		else
309062306a36Sopenharmony_ci			phba->hdwqstat_on |= LPFC_CHECK_NVME_IO;
309162306a36Sopenharmony_ci		return strlen(pbuf);
309262306a36Sopenharmony_ci	} else if ((strncmp(pbuf, "scsi_on", sizeof("scsi_on") - 1) == 0)) {
309362306a36Sopenharmony_ci		if (!phba->nvmet_support)
309462306a36Sopenharmony_ci			phba->hdwqstat_on |= LPFC_CHECK_SCSI_IO;
309562306a36Sopenharmony_ci		return strlen(pbuf);
309662306a36Sopenharmony_ci	} else if ((strncmp(pbuf, "nvme_off", sizeof("nvme_off") - 1) == 0)) {
309762306a36Sopenharmony_ci		phba->hdwqstat_on &= ~(LPFC_CHECK_NVME_IO |
309862306a36Sopenharmony_ci				       LPFC_CHECK_NVMET_IO);
309962306a36Sopenharmony_ci		return strlen(pbuf);
310062306a36Sopenharmony_ci	} else if ((strncmp(pbuf, "scsi_off", sizeof("scsi_off") - 1) == 0)) {
310162306a36Sopenharmony_ci		phba->hdwqstat_on &= ~LPFC_CHECK_SCSI_IO;
310262306a36Sopenharmony_ci		return strlen(pbuf);
310362306a36Sopenharmony_ci	} else if ((strncmp(pbuf, "off",
310462306a36Sopenharmony_ci		   sizeof("off") - 1) == 0)) {
310562306a36Sopenharmony_ci		phba->hdwqstat_on = LPFC_CHECK_OFF;
310662306a36Sopenharmony_ci		return strlen(pbuf);
310762306a36Sopenharmony_ci	} else if ((strncmp(pbuf, "zero",
310862306a36Sopenharmony_ci		   sizeof("zero") - 1) == 0)) {
310962306a36Sopenharmony_ci		for_each_present_cpu(i) {
311062306a36Sopenharmony_ci			c_stat = per_cpu_ptr(phba->sli4_hba.c_stat, i);
311162306a36Sopenharmony_ci			c_stat->xmt_io = 0;
311262306a36Sopenharmony_ci			c_stat->cmpl_io = 0;
311362306a36Sopenharmony_ci			c_stat->rcv_io = 0;
311462306a36Sopenharmony_ci		}
311562306a36Sopenharmony_ci		return strlen(pbuf);
311662306a36Sopenharmony_ci	}
311762306a36Sopenharmony_ci	return -EINVAL;
311862306a36Sopenharmony_ci}
311962306a36Sopenharmony_ci
312062306a36Sopenharmony_ci/*
312162306a36Sopenharmony_ci * ---------------------------------
312262306a36Sopenharmony_ci * iDiag debugfs file access methods
312362306a36Sopenharmony_ci * ---------------------------------
312462306a36Sopenharmony_ci *
312562306a36Sopenharmony_ci * All access methods are through the proper SLI4 PCI function's debugfs
312662306a36Sopenharmony_ci * iDiag directory:
312762306a36Sopenharmony_ci *
312862306a36Sopenharmony_ci *     /sys/kernel/debug/lpfc/fn<#>/iDiag
312962306a36Sopenharmony_ci */
313062306a36Sopenharmony_ci
313162306a36Sopenharmony_ci/**
313262306a36Sopenharmony_ci * lpfc_idiag_cmd_get - Get and parse idiag debugfs comands from user space
313362306a36Sopenharmony_ci * @buf: The pointer to the user space buffer.
313462306a36Sopenharmony_ci * @nbytes: The number of bytes in the user space buffer.
313562306a36Sopenharmony_ci * @idiag_cmd: pointer to the idiag command struct.
313662306a36Sopenharmony_ci *
313762306a36Sopenharmony_ci * This routine reads data from debugfs user space buffer and parses the
313862306a36Sopenharmony_ci * buffer for getting the idiag command and arguments. The while space in
313962306a36Sopenharmony_ci * between the set of data is used as the parsing separator.
314062306a36Sopenharmony_ci *
314162306a36Sopenharmony_ci * This routine returns 0 when successful, it returns proper error code
314262306a36Sopenharmony_ci * back to the user space in error conditions.
314362306a36Sopenharmony_ci */
314462306a36Sopenharmony_cistatic int lpfc_idiag_cmd_get(const char __user *buf, size_t nbytes,
314562306a36Sopenharmony_ci			      struct lpfc_idiag_cmd *idiag_cmd)
314662306a36Sopenharmony_ci{
314762306a36Sopenharmony_ci	char mybuf[64];
314862306a36Sopenharmony_ci	char *pbuf, *step_str;
314962306a36Sopenharmony_ci	int i;
315062306a36Sopenharmony_ci	size_t bsize;
315162306a36Sopenharmony_ci
315262306a36Sopenharmony_ci	memset(mybuf, 0, sizeof(mybuf));
315362306a36Sopenharmony_ci	memset(idiag_cmd, 0, sizeof(*idiag_cmd));
315462306a36Sopenharmony_ci	bsize = min(nbytes, (sizeof(mybuf)-1));
315562306a36Sopenharmony_ci
315662306a36Sopenharmony_ci	if (copy_from_user(mybuf, buf, bsize))
315762306a36Sopenharmony_ci		return -EFAULT;
315862306a36Sopenharmony_ci	pbuf = &mybuf[0];
315962306a36Sopenharmony_ci	step_str = strsep(&pbuf, "\t ");
316062306a36Sopenharmony_ci
316162306a36Sopenharmony_ci	/* The opcode must present */
316262306a36Sopenharmony_ci	if (!step_str)
316362306a36Sopenharmony_ci		return -EINVAL;
316462306a36Sopenharmony_ci
316562306a36Sopenharmony_ci	idiag_cmd->opcode = simple_strtol(step_str, NULL, 0);
316662306a36Sopenharmony_ci	if (idiag_cmd->opcode == 0)
316762306a36Sopenharmony_ci		return -EINVAL;
316862306a36Sopenharmony_ci
316962306a36Sopenharmony_ci	for (i = 0; i < LPFC_IDIAG_CMD_DATA_SIZE; i++) {
317062306a36Sopenharmony_ci		step_str = strsep(&pbuf, "\t ");
317162306a36Sopenharmony_ci		if (!step_str)
317262306a36Sopenharmony_ci			return i;
317362306a36Sopenharmony_ci		idiag_cmd->data[i] = simple_strtol(step_str, NULL, 0);
317462306a36Sopenharmony_ci	}
317562306a36Sopenharmony_ci	return i;
317662306a36Sopenharmony_ci}
317762306a36Sopenharmony_ci
317862306a36Sopenharmony_ci/**
317962306a36Sopenharmony_ci * lpfc_idiag_open - idiag open debugfs
318062306a36Sopenharmony_ci * @inode: The inode pointer that contains a pointer to phba.
318162306a36Sopenharmony_ci * @file: The file pointer to attach the file operation.
318262306a36Sopenharmony_ci *
318362306a36Sopenharmony_ci * Description:
318462306a36Sopenharmony_ci * This routine is the entry point for the debugfs open file operation. It
318562306a36Sopenharmony_ci * gets the reference to phba from the i_private field in @inode, it then
318662306a36Sopenharmony_ci * allocates buffer for the file operation, performs the necessary PCI config
318762306a36Sopenharmony_ci * space read into the allocated buffer according to the idiag user command
318862306a36Sopenharmony_ci * setup, and then returns a pointer to buffer in the private_data field in
318962306a36Sopenharmony_ci * @file.
319062306a36Sopenharmony_ci *
319162306a36Sopenharmony_ci * Returns:
319262306a36Sopenharmony_ci * This function returns zero if successful. On error it will return an
319362306a36Sopenharmony_ci * negative error value.
319462306a36Sopenharmony_ci **/
319562306a36Sopenharmony_cistatic int
319662306a36Sopenharmony_cilpfc_idiag_open(struct inode *inode, struct file *file)
319762306a36Sopenharmony_ci{
319862306a36Sopenharmony_ci	struct lpfc_debug *debug;
319962306a36Sopenharmony_ci
320062306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
320162306a36Sopenharmony_ci	if (!debug)
320262306a36Sopenharmony_ci		return -ENOMEM;
320362306a36Sopenharmony_ci
320462306a36Sopenharmony_ci	debug->i_private = inode->i_private;
320562306a36Sopenharmony_ci	debug->buffer = NULL;
320662306a36Sopenharmony_ci	file->private_data = debug;
320762306a36Sopenharmony_ci
320862306a36Sopenharmony_ci	return 0;
320962306a36Sopenharmony_ci}
321062306a36Sopenharmony_ci
321162306a36Sopenharmony_ci/**
321262306a36Sopenharmony_ci * lpfc_idiag_release - Release idiag access file operation
321362306a36Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer. (unused)
321462306a36Sopenharmony_ci * @file: The file pointer that contains the buffer to release.
321562306a36Sopenharmony_ci *
321662306a36Sopenharmony_ci * Description:
321762306a36Sopenharmony_ci * This routine is the generic release routine for the idiag access file
321862306a36Sopenharmony_ci * operation, it frees the buffer that was allocated when the debugfs file
321962306a36Sopenharmony_ci * was opened.
322062306a36Sopenharmony_ci *
322162306a36Sopenharmony_ci * Returns:
322262306a36Sopenharmony_ci * This function returns zero.
322362306a36Sopenharmony_ci **/
322462306a36Sopenharmony_cistatic int
322562306a36Sopenharmony_cilpfc_idiag_release(struct inode *inode, struct file *file)
322662306a36Sopenharmony_ci{
322762306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
322862306a36Sopenharmony_ci
322962306a36Sopenharmony_ci	/* Free the buffers to the file operation */
323062306a36Sopenharmony_ci	kfree(debug->buffer);
323162306a36Sopenharmony_ci	kfree(debug);
323262306a36Sopenharmony_ci
323362306a36Sopenharmony_ci	return 0;
323462306a36Sopenharmony_ci}
323562306a36Sopenharmony_ci
323662306a36Sopenharmony_ci/**
323762306a36Sopenharmony_ci * lpfc_idiag_cmd_release - Release idiag cmd access file operation
323862306a36Sopenharmony_ci * @inode: The inode pointer that contains a vport pointer. (unused)
323962306a36Sopenharmony_ci * @file: The file pointer that contains the buffer to release.
324062306a36Sopenharmony_ci *
324162306a36Sopenharmony_ci * Description:
324262306a36Sopenharmony_ci * This routine frees the buffer that was allocated when the debugfs file
324362306a36Sopenharmony_ci * was opened. It also reset the fields in the idiag command struct in the
324462306a36Sopenharmony_ci * case of command for write operation.
324562306a36Sopenharmony_ci *
324662306a36Sopenharmony_ci * Returns:
324762306a36Sopenharmony_ci * This function returns zero.
324862306a36Sopenharmony_ci **/
324962306a36Sopenharmony_cistatic int
325062306a36Sopenharmony_cilpfc_idiag_cmd_release(struct inode *inode, struct file *file)
325162306a36Sopenharmony_ci{
325262306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
325362306a36Sopenharmony_ci
325462306a36Sopenharmony_ci	if (debug->op == LPFC_IDIAG_OP_WR) {
325562306a36Sopenharmony_ci		switch (idiag.cmd.opcode) {
325662306a36Sopenharmony_ci		case LPFC_IDIAG_CMD_PCICFG_WR:
325762306a36Sopenharmony_ci		case LPFC_IDIAG_CMD_PCICFG_ST:
325862306a36Sopenharmony_ci		case LPFC_IDIAG_CMD_PCICFG_CL:
325962306a36Sopenharmony_ci		case LPFC_IDIAG_CMD_QUEACC_WR:
326062306a36Sopenharmony_ci		case LPFC_IDIAG_CMD_QUEACC_ST:
326162306a36Sopenharmony_ci		case LPFC_IDIAG_CMD_QUEACC_CL:
326262306a36Sopenharmony_ci			memset(&idiag, 0, sizeof(idiag));
326362306a36Sopenharmony_ci			break;
326462306a36Sopenharmony_ci		default:
326562306a36Sopenharmony_ci			break;
326662306a36Sopenharmony_ci		}
326762306a36Sopenharmony_ci	}
326862306a36Sopenharmony_ci
326962306a36Sopenharmony_ci	/* Free the buffers to the file operation */
327062306a36Sopenharmony_ci	kfree(debug->buffer);
327162306a36Sopenharmony_ci	kfree(debug);
327262306a36Sopenharmony_ci
327362306a36Sopenharmony_ci	return 0;
327462306a36Sopenharmony_ci}
327562306a36Sopenharmony_ci
327662306a36Sopenharmony_ci/**
327762306a36Sopenharmony_ci * lpfc_idiag_pcicfg_read - idiag debugfs read pcicfg
327862306a36Sopenharmony_ci * @file: The file pointer to read from.
327962306a36Sopenharmony_ci * @buf: The buffer to copy the data to.
328062306a36Sopenharmony_ci * @nbytes: The number of bytes to read.
328162306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
328262306a36Sopenharmony_ci *
328362306a36Sopenharmony_ci * Description:
328462306a36Sopenharmony_ci * This routine reads data from the @phba pci config space according to the
328562306a36Sopenharmony_ci * idiag command, and copies to user @buf. Depending on the PCI config space
328662306a36Sopenharmony_ci * read command setup, it does either a single register read of a byte
328762306a36Sopenharmony_ci * (8 bits), a word (16 bits), or a dword (32 bits) or browsing through all
328862306a36Sopenharmony_ci * registers from the 4K extended PCI config space.
328962306a36Sopenharmony_ci *
329062306a36Sopenharmony_ci * Returns:
329162306a36Sopenharmony_ci * This function returns the amount of data that was read (this could be less
329262306a36Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value.
329362306a36Sopenharmony_ci **/
329462306a36Sopenharmony_cistatic ssize_t
329562306a36Sopenharmony_cilpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes,
329662306a36Sopenharmony_ci		       loff_t *ppos)
329762306a36Sopenharmony_ci{
329862306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
329962306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
330062306a36Sopenharmony_ci	int offset_label, offset, len = 0, index = LPFC_PCI_CFG_RD_SIZE;
330162306a36Sopenharmony_ci	int where, count;
330262306a36Sopenharmony_ci	char *pbuffer;
330362306a36Sopenharmony_ci	struct pci_dev *pdev;
330462306a36Sopenharmony_ci	uint32_t u32val;
330562306a36Sopenharmony_ci	uint16_t u16val;
330662306a36Sopenharmony_ci	uint8_t u8val;
330762306a36Sopenharmony_ci
330862306a36Sopenharmony_ci	pdev = phba->pcidev;
330962306a36Sopenharmony_ci	if (!pdev)
331062306a36Sopenharmony_ci		return 0;
331162306a36Sopenharmony_ci
331262306a36Sopenharmony_ci	/* This is a user read operation */
331362306a36Sopenharmony_ci	debug->op = LPFC_IDIAG_OP_RD;
331462306a36Sopenharmony_ci
331562306a36Sopenharmony_ci	if (!debug->buffer)
331662306a36Sopenharmony_ci		debug->buffer = kmalloc(LPFC_PCI_CFG_SIZE, GFP_KERNEL);
331762306a36Sopenharmony_ci	if (!debug->buffer)
331862306a36Sopenharmony_ci		return 0;
331962306a36Sopenharmony_ci	pbuffer = debug->buffer;
332062306a36Sopenharmony_ci
332162306a36Sopenharmony_ci	if (*ppos)
332262306a36Sopenharmony_ci		return 0;
332362306a36Sopenharmony_ci
332462306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) {
332562306a36Sopenharmony_ci		where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
332662306a36Sopenharmony_ci		count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
332762306a36Sopenharmony_ci	} else
332862306a36Sopenharmony_ci		return 0;
332962306a36Sopenharmony_ci
333062306a36Sopenharmony_ci	/* Read single PCI config space register */
333162306a36Sopenharmony_ci	switch (count) {
333262306a36Sopenharmony_ci	case SIZE_U8: /* byte (8 bits) */
333362306a36Sopenharmony_ci		pci_read_config_byte(pdev, where, &u8val);
333462306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
333562306a36Sopenharmony_ci				"%03x: %02x\n", where, u8val);
333662306a36Sopenharmony_ci		break;
333762306a36Sopenharmony_ci	case SIZE_U16: /* word (16 bits) */
333862306a36Sopenharmony_ci		pci_read_config_word(pdev, where, &u16val);
333962306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
334062306a36Sopenharmony_ci				"%03x: %04x\n", where, u16val);
334162306a36Sopenharmony_ci		break;
334262306a36Sopenharmony_ci	case SIZE_U32: /* double word (32 bits) */
334362306a36Sopenharmony_ci		pci_read_config_dword(pdev, where, &u32val);
334462306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
334562306a36Sopenharmony_ci				"%03x: %08x\n", where, u32val);
334662306a36Sopenharmony_ci		break;
334762306a36Sopenharmony_ci	case LPFC_PCI_CFG_BROWSE: /* browse all */
334862306a36Sopenharmony_ci		goto pcicfg_browse;
334962306a36Sopenharmony_ci	default:
335062306a36Sopenharmony_ci		/* illegal count */
335162306a36Sopenharmony_ci		len = 0;
335262306a36Sopenharmony_ci		break;
335362306a36Sopenharmony_ci	}
335462306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
335562306a36Sopenharmony_ci
335662306a36Sopenharmony_cipcicfg_browse:
335762306a36Sopenharmony_ci
335862306a36Sopenharmony_ci	/* Browse all PCI config space registers */
335962306a36Sopenharmony_ci	offset_label = idiag.offset.last_rd;
336062306a36Sopenharmony_ci	offset = offset_label;
336162306a36Sopenharmony_ci
336262306a36Sopenharmony_ci	/* Read PCI config space */
336362306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
336462306a36Sopenharmony_ci			"%03x: ", offset_label);
336562306a36Sopenharmony_ci	while (index > 0) {
336662306a36Sopenharmony_ci		pci_read_config_dword(pdev, offset, &u32val);
336762306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
336862306a36Sopenharmony_ci				"%08x ", u32val);
336962306a36Sopenharmony_ci		offset += sizeof(uint32_t);
337062306a36Sopenharmony_ci		if (offset >= LPFC_PCI_CFG_SIZE) {
337162306a36Sopenharmony_ci			len += scnprintf(pbuffer+len,
337262306a36Sopenharmony_ci					LPFC_PCI_CFG_SIZE-len, "\n");
337362306a36Sopenharmony_ci			break;
337462306a36Sopenharmony_ci		}
337562306a36Sopenharmony_ci		index -= sizeof(uint32_t);
337662306a36Sopenharmony_ci		if (!index)
337762306a36Sopenharmony_ci			len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
337862306a36Sopenharmony_ci					"\n");
337962306a36Sopenharmony_ci		else if (!(index % (8 * sizeof(uint32_t)))) {
338062306a36Sopenharmony_ci			offset_label += (8 * sizeof(uint32_t));
338162306a36Sopenharmony_ci			len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
338262306a36Sopenharmony_ci					"\n%03x: ", offset_label);
338362306a36Sopenharmony_ci		}
338462306a36Sopenharmony_ci	}
338562306a36Sopenharmony_ci
338662306a36Sopenharmony_ci	/* Set up the offset for next portion of pci cfg read */
338762306a36Sopenharmony_ci	if (index == 0) {
338862306a36Sopenharmony_ci		idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE;
338962306a36Sopenharmony_ci		if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE)
339062306a36Sopenharmony_ci			idiag.offset.last_rd = 0;
339162306a36Sopenharmony_ci	} else
339262306a36Sopenharmony_ci		idiag.offset.last_rd = 0;
339362306a36Sopenharmony_ci
339462306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
339562306a36Sopenharmony_ci}
339662306a36Sopenharmony_ci
339762306a36Sopenharmony_ci/**
339862306a36Sopenharmony_ci * lpfc_idiag_pcicfg_write - Syntax check and set up idiag pcicfg commands
339962306a36Sopenharmony_ci * @file: The file pointer to read from.
340062306a36Sopenharmony_ci * @buf: The buffer to copy the user data from.
340162306a36Sopenharmony_ci * @nbytes: The number of bytes to get.
340262306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
340362306a36Sopenharmony_ci *
340462306a36Sopenharmony_ci * This routine get the debugfs idiag command struct from user space and
340562306a36Sopenharmony_ci * then perform the syntax check for PCI config space read or write command
340662306a36Sopenharmony_ci * accordingly. In the case of PCI config space read command, it sets up
340762306a36Sopenharmony_ci * the command in the idiag command struct for the debugfs read operation.
340862306a36Sopenharmony_ci * In the case of PCI config space write operation, it executes the write
340962306a36Sopenharmony_ci * operation into the PCI config space accordingly.
341062306a36Sopenharmony_ci *
341162306a36Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful.
341262306a36Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user
341362306a36Sopenharmony_ci * space.
341462306a36Sopenharmony_ci */
341562306a36Sopenharmony_cistatic ssize_t
341662306a36Sopenharmony_cilpfc_idiag_pcicfg_write(struct file *file, const char __user *buf,
341762306a36Sopenharmony_ci			size_t nbytes, loff_t *ppos)
341862306a36Sopenharmony_ci{
341962306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
342062306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
342162306a36Sopenharmony_ci	uint32_t where, value, count;
342262306a36Sopenharmony_ci	uint32_t u32val;
342362306a36Sopenharmony_ci	uint16_t u16val;
342462306a36Sopenharmony_ci	uint8_t u8val;
342562306a36Sopenharmony_ci	struct pci_dev *pdev;
342662306a36Sopenharmony_ci	int rc;
342762306a36Sopenharmony_ci
342862306a36Sopenharmony_ci	pdev = phba->pcidev;
342962306a36Sopenharmony_ci	if (!pdev)
343062306a36Sopenharmony_ci		return -EFAULT;
343162306a36Sopenharmony_ci
343262306a36Sopenharmony_ci	/* This is a user write operation */
343362306a36Sopenharmony_ci	debug->op = LPFC_IDIAG_OP_WR;
343462306a36Sopenharmony_ci
343562306a36Sopenharmony_ci	rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
343662306a36Sopenharmony_ci	if (rc < 0)
343762306a36Sopenharmony_ci		return rc;
343862306a36Sopenharmony_ci
343962306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) {
344062306a36Sopenharmony_ci		/* Sanity check on PCI config read command line arguments */
344162306a36Sopenharmony_ci		if (rc != LPFC_PCI_CFG_RD_CMD_ARG)
344262306a36Sopenharmony_ci			goto error_out;
344362306a36Sopenharmony_ci		/* Read command from PCI config space, set up command fields */
344462306a36Sopenharmony_ci		where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
344562306a36Sopenharmony_ci		count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
344662306a36Sopenharmony_ci		if (count == LPFC_PCI_CFG_BROWSE) {
344762306a36Sopenharmony_ci			if (where % sizeof(uint32_t))
344862306a36Sopenharmony_ci				goto error_out;
344962306a36Sopenharmony_ci			/* Starting offset to browse */
345062306a36Sopenharmony_ci			idiag.offset.last_rd = where;
345162306a36Sopenharmony_ci		} else if ((count != sizeof(uint8_t)) &&
345262306a36Sopenharmony_ci			   (count != sizeof(uint16_t)) &&
345362306a36Sopenharmony_ci			   (count != sizeof(uint32_t)))
345462306a36Sopenharmony_ci			goto error_out;
345562306a36Sopenharmony_ci		if (count == sizeof(uint8_t)) {
345662306a36Sopenharmony_ci			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t))
345762306a36Sopenharmony_ci				goto error_out;
345862306a36Sopenharmony_ci			if (where % sizeof(uint8_t))
345962306a36Sopenharmony_ci				goto error_out;
346062306a36Sopenharmony_ci		}
346162306a36Sopenharmony_ci		if (count == sizeof(uint16_t)) {
346262306a36Sopenharmony_ci			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t))
346362306a36Sopenharmony_ci				goto error_out;
346462306a36Sopenharmony_ci			if (where % sizeof(uint16_t))
346562306a36Sopenharmony_ci				goto error_out;
346662306a36Sopenharmony_ci		}
346762306a36Sopenharmony_ci		if (count == sizeof(uint32_t)) {
346862306a36Sopenharmony_ci			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t))
346962306a36Sopenharmony_ci				goto error_out;
347062306a36Sopenharmony_ci			if (where % sizeof(uint32_t))
347162306a36Sopenharmony_ci				goto error_out;
347262306a36Sopenharmony_ci		}
347362306a36Sopenharmony_ci	} else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR ||
347462306a36Sopenharmony_ci		   idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST ||
347562306a36Sopenharmony_ci		   idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
347662306a36Sopenharmony_ci		/* Sanity check on PCI config write command line arguments */
347762306a36Sopenharmony_ci		if (rc != LPFC_PCI_CFG_WR_CMD_ARG)
347862306a36Sopenharmony_ci			goto error_out;
347962306a36Sopenharmony_ci		/* Write command to PCI config space, read-modify-write */
348062306a36Sopenharmony_ci		where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
348162306a36Sopenharmony_ci		count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
348262306a36Sopenharmony_ci		value = idiag.cmd.data[IDIAG_PCICFG_VALUE_INDX];
348362306a36Sopenharmony_ci		/* Sanity checks */
348462306a36Sopenharmony_ci		if ((count != sizeof(uint8_t)) &&
348562306a36Sopenharmony_ci		    (count != sizeof(uint16_t)) &&
348662306a36Sopenharmony_ci		    (count != sizeof(uint32_t)))
348762306a36Sopenharmony_ci			goto error_out;
348862306a36Sopenharmony_ci		if (count == sizeof(uint8_t)) {
348962306a36Sopenharmony_ci			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t))
349062306a36Sopenharmony_ci				goto error_out;
349162306a36Sopenharmony_ci			if (where % sizeof(uint8_t))
349262306a36Sopenharmony_ci				goto error_out;
349362306a36Sopenharmony_ci			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
349462306a36Sopenharmony_ci				pci_write_config_byte(pdev, where,
349562306a36Sopenharmony_ci						      (uint8_t)value);
349662306a36Sopenharmony_ci			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
349762306a36Sopenharmony_ci				rc = pci_read_config_byte(pdev, where, &u8val);
349862306a36Sopenharmony_ci				if (!rc) {
349962306a36Sopenharmony_ci					u8val |= (uint8_t)value;
350062306a36Sopenharmony_ci					pci_write_config_byte(pdev, where,
350162306a36Sopenharmony_ci							      u8val);
350262306a36Sopenharmony_ci				}
350362306a36Sopenharmony_ci			}
350462306a36Sopenharmony_ci			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
350562306a36Sopenharmony_ci				rc = pci_read_config_byte(pdev, where, &u8val);
350662306a36Sopenharmony_ci				if (!rc) {
350762306a36Sopenharmony_ci					u8val &= (uint8_t)(~value);
350862306a36Sopenharmony_ci					pci_write_config_byte(pdev, where,
350962306a36Sopenharmony_ci							      u8val);
351062306a36Sopenharmony_ci				}
351162306a36Sopenharmony_ci			}
351262306a36Sopenharmony_ci		}
351362306a36Sopenharmony_ci		if (count == sizeof(uint16_t)) {
351462306a36Sopenharmony_ci			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t))
351562306a36Sopenharmony_ci				goto error_out;
351662306a36Sopenharmony_ci			if (where % sizeof(uint16_t))
351762306a36Sopenharmony_ci				goto error_out;
351862306a36Sopenharmony_ci			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
351962306a36Sopenharmony_ci				pci_write_config_word(pdev, where,
352062306a36Sopenharmony_ci						      (uint16_t)value);
352162306a36Sopenharmony_ci			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
352262306a36Sopenharmony_ci				rc = pci_read_config_word(pdev, where, &u16val);
352362306a36Sopenharmony_ci				if (!rc) {
352462306a36Sopenharmony_ci					u16val |= (uint16_t)value;
352562306a36Sopenharmony_ci					pci_write_config_word(pdev, where,
352662306a36Sopenharmony_ci							      u16val);
352762306a36Sopenharmony_ci				}
352862306a36Sopenharmony_ci			}
352962306a36Sopenharmony_ci			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
353062306a36Sopenharmony_ci				rc = pci_read_config_word(pdev, where, &u16val);
353162306a36Sopenharmony_ci				if (!rc) {
353262306a36Sopenharmony_ci					u16val &= (uint16_t)(~value);
353362306a36Sopenharmony_ci					pci_write_config_word(pdev, where,
353462306a36Sopenharmony_ci							      u16val);
353562306a36Sopenharmony_ci				}
353662306a36Sopenharmony_ci			}
353762306a36Sopenharmony_ci		}
353862306a36Sopenharmony_ci		if (count == sizeof(uint32_t)) {
353962306a36Sopenharmony_ci			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t))
354062306a36Sopenharmony_ci				goto error_out;
354162306a36Sopenharmony_ci			if (where % sizeof(uint32_t))
354262306a36Sopenharmony_ci				goto error_out;
354362306a36Sopenharmony_ci			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
354462306a36Sopenharmony_ci				pci_write_config_dword(pdev, where, value);
354562306a36Sopenharmony_ci			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
354662306a36Sopenharmony_ci				rc = pci_read_config_dword(pdev, where,
354762306a36Sopenharmony_ci							   &u32val);
354862306a36Sopenharmony_ci				if (!rc) {
354962306a36Sopenharmony_ci					u32val |= value;
355062306a36Sopenharmony_ci					pci_write_config_dword(pdev, where,
355162306a36Sopenharmony_ci							       u32val);
355262306a36Sopenharmony_ci				}
355362306a36Sopenharmony_ci			}
355462306a36Sopenharmony_ci			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
355562306a36Sopenharmony_ci				rc = pci_read_config_dword(pdev, where,
355662306a36Sopenharmony_ci							   &u32val);
355762306a36Sopenharmony_ci				if (!rc) {
355862306a36Sopenharmony_ci					u32val &= ~value;
355962306a36Sopenharmony_ci					pci_write_config_dword(pdev, where,
356062306a36Sopenharmony_ci							       u32val);
356162306a36Sopenharmony_ci				}
356262306a36Sopenharmony_ci			}
356362306a36Sopenharmony_ci		}
356462306a36Sopenharmony_ci	} else
356562306a36Sopenharmony_ci		/* All other opecodes are illegal for now */
356662306a36Sopenharmony_ci		goto error_out;
356762306a36Sopenharmony_ci
356862306a36Sopenharmony_ci	return nbytes;
356962306a36Sopenharmony_cierror_out:
357062306a36Sopenharmony_ci	memset(&idiag, 0, sizeof(idiag));
357162306a36Sopenharmony_ci	return -EINVAL;
357262306a36Sopenharmony_ci}
357362306a36Sopenharmony_ci
357462306a36Sopenharmony_ci/**
357562306a36Sopenharmony_ci * lpfc_idiag_baracc_read - idiag debugfs pci bar access read
357662306a36Sopenharmony_ci * @file: The file pointer to read from.
357762306a36Sopenharmony_ci * @buf: The buffer to copy the data to.
357862306a36Sopenharmony_ci * @nbytes: The number of bytes to read.
357962306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
358062306a36Sopenharmony_ci *
358162306a36Sopenharmony_ci * Description:
358262306a36Sopenharmony_ci * This routine reads data from the @phba pci bar memory mapped space
358362306a36Sopenharmony_ci * according to the idiag command, and copies to user @buf.
358462306a36Sopenharmony_ci *
358562306a36Sopenharmony_ci * Returns:
358662306a36Sopenharmony_ci * This function returns the amount of data that was read (this could be less
358762306a36Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value.
358862306a36Sopenharmony_ci **/
358962306a36Sopenharmony_cistatic ssize_t
359062306a36Sopenharmony_cilpfc_idiag_baracc_read(struct file *file, char __user *buf, size_t nbytes,
359162306a36Sopenharmony_ci		       loff_t *ppos)
359262306a36Sopenharmony_ci{
359362306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
359462306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
359562306a36Sopenharmony_ci	int offset_label, offset, offset_run, len = 0, index;
359662306a36Sopenharmony_ci	int bar_num, acc_range, bar_size;
359762306a36Sopenharmony_ci	char *pbuffer;
359862306a36Sopenharmony_ci	void __iomem *mem_mapped_bar;
359962306a36Sopenharmony_ci	uint32_t if_type;
360062306a36Sopenharmony_ci	struct pci_dev *pdev;
360162306a36Sopenharmony_ci	uint32_t u32val;
360262306a36Sopenharmony_ci
360362306a36Sopenharmony_ci	pdev = phba->pcidev;
360462306a36Sopenharmony_ci	if (!pdev)
360562306a36Sopenharmony_ci		return 0;
360662306a36Sopenharmony_ci
360762306a36Sopenharmony_ci	/* This is a user read operation */
360862306a36Sopenharmony_ci	debug->op = LPFC_IDIAG_OP_RD;
360962306a36Sopenharmony_ci
361062306a36Sopenharmony_ci	if (!debug->buffer)
361162306a36Sopenharmony_ci		debug->buffer = kmalloc(LPFC_PCI_BAR_RD_BUF_SIZE, GFP_KERNEL);
361262306a36Sopenharmony_ci	if (!debug->buffer)
361362306a36Sopenharmony_ci		return 0;
361462306a36Sopenharmony_ci	pbuffer = debug->buffer;
361562306a36Sopenharmony_ci
361662306a36Sopenharmony_ci	if (*ppos)
361762306a36Sopenharmony_ci		return 0;
361862306a36Sopenharmony_ci
361962306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) {
362062306a36Sopenharmony_ci		bar_num   = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX];
362162306a36Sopenharmony_ci		offset    = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX];
362262306a36Sopenharmony_ci		acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX];
362362306a36Sopenharmony_ci		bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX];
362462306a36Sopenharmony_ci	} else
362562306a36Sopenharmony_ci		return 0;
362662306a36Sopenharmony_ci
362762306a36Sopenharmony_ci	if (acc_range == 0)
362862306a36Sopenharmony_ci		return 0;
362962306a36Sopenharmony_ci
363062306a36Sopenharmony_ci	if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
363162306a36Sopenharmony_ci	if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
363262306a36Sopenharmony_ci		if (bar_num == IDIAG_BARACC_BAR_0)
363362306a36Sopenharmony_ci			mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
363462306a36Sopenharmony_ci		else if (bar_num == IDIAG_BARACC_BAR_1)
363562306a36Sopenharmony_ci			mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p;
363662306a36Sopenharmony_ci		else if (bar_num == IDIAG_BARACC_BAR_2)
363762306a36Sopenharmony_ci			mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p;
363862306a36Sopenharmony_ci		else
363962306a36Sopenharmony_ci			return 0;
364062306a36Sopenharmony_ci	} else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
364162306a36Sopenharmony_ci		if (bar_num == IDIAG_BARACC_BAR_0)
364262306a36Sopenharmony_ci			mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
364362306a36Sopenharmony_ci		else
364462306a36Sopenharmony_ci			return 0;
364562306a36Sopenharmony_ci	} else
364662306a36Sopenharmony_ci		return 0;
364762306a36Sopenharmony_ci
364862306a36Sopenharmony_ci	/* Read single PCI bar space register */
364962306a36Sopenharmony_ci	if (acc_range == SINGLE_WORD) {
365062306a36Sopenharmony_ci		offset_run = offset;
365162306a36Sopenharmony_ci		u32val = readl(mem_mapped_bar + offset_run);
365262306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
365362306a36Sopenharmony_ci				"%05x: %08x\n", offset_run, u32val);
365462306a36Sopenharmony_ci	} else
365562306a36Sopenharmony_ci		goto baracc_browse;
365662306a36Sopenharmony_ci
365762306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
365862306a36Sopenharmony_ci
365962306a36Sopenharmony_cibaracc_browse:
366062306a36Sopenharmony_ci
366162306a36Sopenharmony_ci	/* Browse all PCI bar space registers */
366262306a36Sopenharmony_ci	offset_label = idiag.offset.last_rd;
366362306a36Sopenharmony_ci	offset_run = offset_label;
366462306a36Sopenharmony_ci
366562306a36Sopenharmony_ci	/* Read PCI bar memory mapped space */
366662306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
366762306a36Sopenharmony_ci			"%05x: ", offset_label);
366862306a36Sopenharmony_ci	index = LPFC_PCI_BAR_RD_SIZE;
366962306a36Sopenharmony_ci	while (index > 0) {
367062306a36Sopenharmony_ci		u32val = readl(mem_mapped_bar + offset_run);
367162306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
367262306a36Sopenharmony_ci				"%08x ", u32val);
367362306a36Sopenharmony_ci		offset_run += sizeof(uint32_t);
367462306a36Sopenharmony_ci		if (acc_range == LPFC_PCI_BAR_BROWSE) {
367562306a36Sopenharmony_ci			if (offset_run >= bar_size) {
367662306a36Sopenharmony_ci				len += scnprintf(pbuffer+len,
367762306a36Sopenharmony_ci					LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
367862306a36Sopenharmony_ci				break;
367962306a36Sopenharmony_ci			}
368062306a36Sopenharmony_ci		} else {
368162306a36Sopenharmony_ci			if (offset_run >= offset +
368262306a36Sopenharmony_ci			    (acc_range * sizeof(uint32_t))) {
368362306a36Sopenharmony_ci				len += scnprintf(pbuffer+len,
368462306a36Sopenharmony_ci					LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
368562306a36Sopenharmony_ci				break;
368662306a36Sopenharmony_ci			}
368762306a36Sopenharmony_ci		}
368862306a36Sopenharmony_ci		index -= sizeof(uint32_t);
368962306a36Sopenharmony_ci		if (!index)
369062306a36Sopenharmony_ci			len += scnprintf(pbuffer+len,
369162306a36Sopenharmony_ci					LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
369262306a36Sopenharmony_ci		else if (!(index % (8 * sizeof(uint32_t)))) {
369362306a36Sopenharmony_ci			offset_label += (8 * sizeof(uint32_t));
369462306a36Sopenharmony_ci			len += scnprintf(pbuffer+len,
369562306a36Sopenharmony_ci					LPFC_PCI_BAR_RD_BUF_SIZE-len,
369662306a36Sopenharmony_ci					"\n%05x: ", offset_label);
369762306a36Sopenharmony_ci		}
369862306a36Sopenharmony_ci	}
369962306a36Sopenharmony_ci
370062306a36Sopenharmony_ci	/* Set up the offset for next portion of pci bar read */
370162306a36Sopenharmony_ci	if (index == 0) {
370262306a36Sopenharmony_ci		idiag.offset.last_rd += LPFC_PCI_BAR_RD_SIZE;
370362306a36Sopenharmony_ci		if (acc_range == LPFC_PCI_BAR_BROWSE) {
370462306a36Sopenharmony_ci			if (idiag.offset.last_rd >= bar_size)
370562306a36Sopenharmony_ci				idiag.offset.last_rd = 0;
370662306a36Sopenharmony_ci		} else {
370762306a36Sopenharmony_ci			if (offset_run >= offset +
370862306a36Sopenharmony_ci			    (acc_range * sizeof(uint32_t)))
370962306a36Sopenharmony_ci				idiag.offset.last_rd = offset;
371062306a36Sopenharmony_ci		}
371162306a36Sopenharmony_ci	} else {
371262306a36Sopenharmony_ci		if (acc_range == LPFC_PCI_BAR_BROWSE)
371362306a36Sopenharmony_ci			idiag.offset.last_rd = 0;
371462306a36Sopenharmony_ci		else
371562306a36Sopenharmony_ci			idiag.offset.last_rd = offset;
371662306a36Sopenharmony_ci	}
371762306a36Sopenharmony_ci
371862306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
371962306a36Sopenharmony_ci}
372062306a36Sopenharmony_ci
372162306a36Sopenharmony_ci/**
372262306a36Sopenharmony_ci * lpfc_idiag_baracc_write - Syntax check and set up idiag bar access commands
372362306a36Sopenharmony_ci * @file: The file pointer to read from.
372462306a36Sopenharmony_ci * @buf: The buffer to copy the user data from.
372562306a36Sopenharmony_ci * @nbytes: The number of bytes to get.
372662306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
372762306a36Sopenharmony_ci *
372862306a36Sopenharmony_ci * This routine get the debugfs idiag command struct from user space and
372962306a36Sopenharmony_ci * then perform the syntax check for PCI bar memory mapped space read or
373062306a36Sopenharmony_ci * write command accordingly. In the case of PCI bar memory mapped space
373162306a36Sopenharmony_ci * read command, it sets up the command in the idiag command struct for
373262306a36Sopenharmony_ci * the debugfs read operation. In the case of PCI bar memorpy mapped space
373362306a36Sopenharmony_ci * write operation, it executes the write operation into the PCI bar memory
373462306a36Sopenharmony_ci * mapped space accordingly.
373562306a36Sopenharmony_ci *
373662306a36Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful.
373762306a36Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user
373862306a36Sopenharmony_ci * space.
373962306a36Sopenharmony_ci */
374062306a36Sopenharmony_cistatic ssize_t
374162306a36Sopenharmony_cilpfc_idiag_baracc_write(struct file *file, const char __user *buf,
374262306a36Sopenharmony_ci			size_t nbytes, loff_t *ppos)
374362306a36Sopenharmony_ci{
374462306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
374562306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
374662306a36Sopenharmony_ci	uint32_t bar_num, bar_size, offset, value, acc_range;
374762306a36Sopenharmony_ci	struct pci_dev *pdev;
374862306a36Sopenharmony_ci	void __iomem *mem_mapped_bar;
374962306a36Sopenharmony_ci	uint32_t if_type;
375062306a36Sopenharmony_ci	uint32_t u32val;
375162306a36Sopenharmony_ci	int rc;
375262306a36Sopenharmony_ci
375362306a36Sopenharmony_ci	pdev = phba->pcidev;
375462306a36Sopenharmony_ci	if (!pdev)
375562306a36Sopenharmony_ci		return -EFAULT;
375662306a36Sopenharmony_ci
375762306a36Sopenharmony_ci	/* This is a user write operation */
375862306a36Sopenharmony_ci	debug->op = LPFC_IDIAG_OP_WR;
375962306a36Sopenharmony_ci
376062306a36Sopenharmony_ci	rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
376162306a36Sopenharmony_ci	if (rc < 0)
376262306a36Sopenharmony_ci		return rc;
376362306a36Sopenharmony_ci
376462306a36Sopenharmony_ci	if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
376562306a36Sopenharmony_ci	bar_num = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX];
376662306a36Sopenharmony_ci
376762306a36Sopenharmony_ci	if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
376862306a36Sopenharmony_ci		if ((bar_num != IDIAG_BARACC_BAR_0) &&
376962306a36Sopenharmony_ci		    (bar_num != IDIAG_BARACC_BAR_1) &&
377062306a36Sopenharmony_ci		    (bar_num != IDIAG_BARACC_BAR_2))
377162306a36Sopenharmony_ci			goto error_out;
377262306a36Sopenharmony_ci	} else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
377362306a36Sopenharmony_ci		if (bar_num != IDIAG_BARACC_BAR_0)
377462306a36Sopenharmony_ci			goto error_out;
377562306a36Sopenharmony_ci	} else
377662306a36Sopenharmony_ci		goto error_out;
377762306a36Sopenharmony_ci
377862306a36Sopenharmony_ci	if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
377962306a36Sopenharmony_ci		if (bar_num == IDIAG_BARACC_BAR_0) {
378062306a36Sopenharmony_ci			idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
378162306a36Sopenharmony_ci				LPFC_PCI_IF0_BAR0_SIZE;
378262306a36Sopenharmony_ci			mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
378362306a36Sopenharmony_ci		} else if (bar_num == IDIAG_BARACC_BAR_1) {
378462306a36Sopenharmony_ci			idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
378562306a36Sopenharmony_ci				LPFC_PCI_IF0_BAR1_SIZE;
378662306a36Sopenharmony_ci			mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p;
378762306a36Sopenharmony_ci		} else if (bar_num == IDIAG_BARACC_BAR_2) {
378862306a36Sopenharmony_ci			idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
378962306a36Sopenharmony_ci				LPFC_PCI_IF0_BAR2_SIZE;
379062306a36Sopenharmony_ci			mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p;
379162306a36Sopenharmony_ci		} else
379262306a36Sopenharmony_ci			goto error_out;
379362306a36Sopenharmony_ci	} else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
379462306a36Sopenharmony_ci		if (bar_num == IDIAG_BARACC_BAR_0) {
379562306a36Sopenharmony_ci			idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
379662306a36Sopenharmony_ci				LPFC_PCI_IF2_BAR0_SIZE;
379762306a36Sopenharmony_ci			mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
379862306a36Sopenharmony_ci		} else
379962306a36Sopenharmony_ci			goto error_out;
380062306a36Sopenharmony_ci	} else
380162306a36Sopenharmony_ci		goto error_out;
380262306a36Sopenharmony_ci
380362306a36Sopenharmony_ci	offset = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX];
380462306a36Sopenharmony_ci	if (offset % sizeof(uint32_t))
380562306a36Sopenharmony_ci		goto error_out;
380662306a36Sopenharmony_ci
380762306a36Sopenharmony_ci	bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX];
380862306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) {
380962306a36Sopenharmony_ci		/* Sanity check on PCI config read command line arguments */
381062306a36Sopenharmony_ci		if (rc != LPFC_PCI_BAR_RD_CMD_ARG)
381162306a36Sopenharmony_ci			goto error_out;
381262306a36Sopenharmony_ci		acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX];
381362306a36Sopenharmony_ci		if (acc_range == LPFC_PCI_BAR_BROWSE) {
381462306a36Sopenharmony_ci			if (offset > bar_size - sizeof(uint32_t))
381562306a36Sopenharmony_ci				goto error_out;
381662306a36Sopenharmony_ci			/* Starting offset to browse */
381762306a36Sopenharmony_ci			idiag.offset.last_rd = offset;
381862306a36Sopenharmony_ci		} else if (acc_range > SINGLE_WORD) {
381962306a36Sopenharmony_ci			if (offset + acc_range * sizeof(uint32_t) > bar_size)
382062306a36Sopenharmony_ci				goto error_out;
382162306a36Sopenharmony_ci			/* Starting offset to browse */
382262306a36Sopenharmony_ci			idiag.offset.last_rd = offset;
382362306a36Sopenharmony_ci		} else if (acc_range != SINGLE_WORD)
382462306a36Sopenharmony_ci			goto error_out;
382562306a36Sopenharmony_ci	} else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR ||
382662306a36Sopenharmony_ci		   idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST ||
382762306a36Sopenharmony_ci		   idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) {
382862306a36Sopenharmony_ci		/* Sanity check on PCI bar write command line arguments */
382962306a36Sopenharmony_ci		if (rc != LPFC_PCI_BAR_WR_CMD_ARG)
383062306a36Sopenharmony_ci			goto error_out;
383162306a36Sopenharmony_ci		/* Write command to PCI bar space, read-modify-write */
383262306a36Sopenharmony_ci		acc_range = SINGLE_WORD;
383362306a36Sopenharmony_ci		value = idiag.cmd.data[IDIAG_BARACC_REG_VAL_INDX];
383462306a36Sopenharmony_ci		if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR) {
383562306a36Sopenharmony_ci			writel(value, mem_mapped_bar + offset);
383662306a36Sopenharmony_ci			readl(mem_mapped_bar + offset);
383762306a36Sopenharmony_ci		}
383862306a36Sopenharmony_ci		if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST) {
383962306a36Sopenharmony_ci			u32val = readl(mem_mapped_bar + offset);
384062306a36Sopenharmony_ci			u32val |= value;
384162306a36Sopenharmony_ci			writel(u32val, mem_mapped_bar + offset);
384262306a36Sopenharmony_ci			readl(mem_mapped_bar + offset);
384362306a36Sopenharmony_ci		}
384462306a36Sopenharmony_ci		if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) {
384562306a36Sopenharmony_ci			u32val = readl(mem_mapped_bar + offset);
384662306a36Sopenharmony_ci			u32val &= ~value;
384762306a36Sopenharmony_ci			writel(u32val, mem_mapped_bar + offset);
384862306a36Sopenharmony_ci			readl(mem_mapped_bar + offset);
384962306a36Sopenharmony_ci		}
385062306a36Sopenharmony_ci	} else
385162306a36Sopenharmony_ci		/* All other opecodes are illegal for now */
385262306a36Sopenharmony_ci		goto error_out;
385362306a36Sopenharmony_ci
385462306a36Sopenharmony_ci	return nbytes;
385562306a36Sopenharmony_cierror_out:
385662306a36Sopenharmony_ci	memset(&idiag, 0, sizeof(idiag));
385762306a36Sopenharmony_ci	return -EINVAL;
385862306a36Sopenharmony_ci}
385962306a36Sopenharmony_ci
386062306a36Sopenharmony_cistatic int
386162306a36Sopenharmony_ci__lpfc_idiag_print_wq(struct lpfc_queue *qp, char *wqtype,
386262306a36Sopenharmony_ci			char *pbuffer, int len)
386362306a36Sopenharmony_ci{
386462306a36Sopenharmony_ci	if (!qp)
386562306a36Sopenharmony_ci		return len;
386662306a36Sopenharmony_ci
386762306a36Sopenharmony_ci	len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
386862306a36Sopenharmony_ci			"\t\t%s WQ info: ", wqtype);
386962306a36Sopenharmony_ci	len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
387062306a36Sopenharmony_ci			"AssocCQID[%04d]: WQ-STAT[oflow:x%x posted:x%llx]\n",
387162306a36Sopenharmony_ci			qp->assoc_qid, qp->q_cnt_1,
387262306a36Sopenharmony_ci			(unsigned long long)qp->q_cnt_4);
387362306a36Sopenharmony_ci	len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
387462306a36Sopenharmony_ci			"\t\tWQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
387562306a36Sopenharmony_ci			"HST-IDX[%04d], PRT-IDX[%04d], NTFI[%03d]",
387662306a36Sopenharmony_ci			qp->queue_id, qp->entry_count,
387762306a36Sopenharmony_ci			qp->entry_size, qp->host_index,
387862306a36Sopenharmony_ci			qp->hba_index, qp->notify_interval);
387962306a36Sopenharmony_ci	len +=  scnprintf(pbuffer + len,
388062306a36Sopenharmony_ci			LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n");
388162306a36Sopenharmony_ci	return len;
388262306a36Sopenharmony_ci}
388362306a36Sopenharmony_ci
388462306a36Sopenharmony_cistatic int
388562306a36Sopenharmony_cilpfc_idiag_wqs_for_cq(struct lpfc_hba *phba, char *wqtype, char *pbuffer,
388662306a36Sopenharmony_ci		int *len, int max_cnt, int cq_id)
388762306a36Sopenharmony_ci{
388862306a36Sopenharmony_ci	struct lpfc_queue *qp;
388962306a36Sopenharmony_ci	int qidx;
389062306a36Sopenharmony_ci
389162306a36Sopenharmony_ci	for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) {
389262306a36Sopenharmony_ci		qp = phba->sli4_hba.hdwq[qidx].io_wq;
389362306a36Sopenharmony_ci		if (qp->assoc_qid != cq_id)
389462306a36Sopenharmony_ci			continue;
389562306a36Sopenharmony_ci		*len = __lpfc_idiag_print_wq(qp, wqtype, pbuffer, *len);
389662306a36Sopenharmony_ci		if (*len >= max_cnt)
389762306a36Sopenharmony_ci			return 1;
389862306a36Sopenharmony_ci	}
389962306a36Sopenharmony_ci	return 0;
390062306a36Sopenharmony_ci}
390162306a36Sopenharmony_ci
390262306a36Sopenharmony_cistatic int
390362306a36Sopenharmony_ci__lpfc_idiag_print_cq(struct lpfc_queue *qp, char *cqtype,
390462306a36Sopenharmony_ci			char *pbuffer, int len)
390562306a36Sopenharmony_ci{
390662306a36Sopenharmony_ci	if (!qp)
390762306a36Sopenharmony_ci		return len;
390862306a36Sopenharmony_ci
390962306a36Sopenharmony_ci	len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
391062306a36Sopenharmony_ci			"\t%s CQ info: ", cqtype);
391162306a36Sopenharmony_ci	len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
391262306a36Sopenharmony_ci			"AssocEQID[%02d]: CQ STAT[max:x%x relw:x%x "
391362306a36Sopenharmony_ci			"xabt:x%x wq:x%llx]\n",
391462306a36Sopenharmony_ci			qp->assoc_qid, qp->q_cnt_1, qp->q_cnt_2,
391562306a36Sopenharmony_ci			qp->q_cnt_3, (unsigned long long)qp->q_cnt_4);
391662306a36Sopenharmony_ci	len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
391762306a36Sopenharmony_ci			"\tCQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
391862306a36Sopenharmony_ci			"HST-IDX[%04d], NTFI[%03d], PLMT[%03d]",
391962306a36Sopenharmony_ci			qp->queue_id, qp->entry_count,
392062306a36Sopenharmony_ci			qp->entry_size, qp->host_index,
392162306a36Sopenharmony_ci			qp->notify_interval, qp->max_proc_limit);
392262306a36Sopenharmony_ci
392362306a36Sopenharmony_ci	len +=  scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
392462306a36Sopenharmony_ci			"\n");
392562306a36Sopenharmony_ci
392662306a36Sopenharmony_ci	return len;
392762306a36Sopenharmony_ci}
392862306a36Sopenharmony_ci
392962306a36Sopenharmony_cistatic int
393062306a36Sopenharmony_ci__lpfc_idiag_print_rqpair(struct lpfc_queue *qp, struct lpfc_queue *datqp,
393162306a36Sopenharmony_ci			char *rqtype, char *pbuffer, int len)
393262306a36Sopenharmony_ci{
393362306a36Sopenharmony_ci	if (!qp || !datqp)
393462306a36Sopenharmony_ci		return len;
393562306a36Sopenharmony_ci
393662306a36Sopenharmony_ci	len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
393762306a36Sopenharmony_ci			"\t\t%s RQ info: ", rqtype);
393862306a36Sopenharmony_ci	len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
393962306a36Sopenharmony_ci			"AssocCQID[%02d]: RQ-STAT[nopost:x%x nobuf:x%x "
394062306a36Sopenharmony_ci			"posted:x%x rcv:x%llx]\n",
394162306a36Sopenharmony_ci			qp->assoc_qid, qp->q_cnt_1, qp->q_cnt_2,
394262306a36Sopenharmony_ci			qp->q_cnt_3, (unsigned long long)qp->q_cnt_4);
394362306a36Sopenharmony_ci	len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
394462306a36Sopenharmony_ci			"\t\tHQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
394562306a36Sopenharmony_ci			"HST-IDX[%04d], PRT-IDX[%04d], NTFI[%03d]\n",
394662306a36Sopenharmony_ci			qp->queue_id, qp->entry_count, qp->entry_size,
394762306a36Sopenharmony_ci			qp->host_index, qp->hba_index, qp->notify_interval);
394862306a36Sopenharmony_ci	len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
394962306a36Sopenharmony_ci			"\t\tDQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
395062306a36Sopenharmony_ci			"HST-IDX[%04d], PRT-IDX[%04d], NTFI[%03d]\n",
395162306a36Sopenharmony_ci			datqp->queue_id, datqp->entry_count,
395262306a36Sopenharmony_ci			datqp->entry_size, datqp->host_index,
395362306a36Sopenharmony_ci			datqp->hba_index, datqp->notify_interval);
395462306a36Sopenharmony_ci	return len;
395562306a36Sopenharmony_ci}
395662306a36Sopenharmony_ci
395762306a36Sopenharmony_cistatic int
395862306a36Sopenharmony_cilpfc_idiag_cqs_for_eq(struct lpfc_hba *phba, char *pbuffer,
395962306a36Sopenharmony_ci		int *len, int max_cnt, int eqidx, int eq_id)
396062306a36Sopenharmony_ci{
396162306a36Sopenharmony_ci	struct lpfc_queue *qp;
396262306a36Sopenharmony_ci	int rc;
396362306a36Sopenharmony_ci
396462306a36Sopenharmony_ci	qp = phba->sli4_hba.hdwq[eqidx].io_cq;
396562306a36Sopenharmony_ci
396662306a36Sopenharmony_ci	*len = __lpfc_idiag_print_cq(qp, "IO", pbuffer, *len);
396762306a36Sopenharmony_ci
396862306a36Sopenharmony_ci	/* Reset max counter */
396962306a36Sopenharmony_ci	qp->CQ_max_cqe = 0;
397062306a36Sopenharmony_ci
397162306a36Sopenharmony_ci	if (*len >= max_cnt)
397262306a36Sopenharmony_ci		return 1;
397362306a36Sopenharmony_ci
397462306a36Sopenharmony_ci	rc = lpfc_idiag_wqs_for_cq(phba, "IO", pbuffer, len,
397562306a36Sopenharmony_ci				   max_cnt, qp->queue_id);
397662306a36Sopenharmony_ci	if (rc)
397762306a36Sopenharmony_ci		return 1;
397862306a36Sopenharmony_ci
397962306a36Sopenharmony_ci	if ((eqidx < phba->cfg_nvmet_mrq) && phba->nvmet_support) {
398062306a36Sopenharmony_ci		/* NVMET CQset */
398162306a36Sopenharmony_ci		qp = phba->sli4_hba.nvmet_cqset[eqidx];
398262306a36Sopenharmony_ci		*len = __lpfc_idiag_print_cq(qp, "NVMET CQset", pbuffer, *len);
398362306a36Sopenharmony_ci
398462306a36Sopenharmony_ci		/* Reset max counter */
398562306a36Sopenharmony_ci		qp->CQ_max_cqe = 0;
398662306a36Sopenharmony_ci
398762306a36Sopenharmony_ci		if (*len >= max_cnt)
398862306a36Sopenharmony_ci			return 1;
398962306a36Sopenharmony_ci
399062306a36Sopenharmony_ci		/* RQ header */
399162306a36Sopenharmony_ci		qp = phba->sli4_hba.nvmet_mrq_hdr[eqidx];
399262306a36Sopenharmony_ci		*len = __lpfc_idiag_print_rqpair(qp,
399362306a36Sopenharmony_ci				phba->sli4_hba.nvmet_mrq_data[eqidx],
399462306a36Sopenharmony_ci				"NVMET MRQ", pbuffer, *len);
399562306a36Sopenharmony_ci
399662306a36Sopenharmony_ci		if (*len >= max_cnt)
399762306a36Sopenharmony_ci			return 1;
399862306a36Sopenharmony_ci	}
399962306a36Sopenharmony_ci
400062306a36Sopenharmony_ci	return 0;
400162306a36Sopenharmony_ci}
400262306a36Sopenharmony_ci
400362306a36Sopenharmony_cistatic int
400462306a36Sopenharmony_ci__lpfc_idiag_print_eq(struct lpfc_queue *qp, char *eqtype,
400562306a36Sopenharmony_ci			char *pbuffer, int len)
400662306a36Sopenharmony_ci{
400762306a36Sopenharmony_ci	if (!qp)
400862306a36Sopenharmony_ci		return len;
400962306a36Sopenharmony_ci
401062306a36Sopenharmony_ci	len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
401162306a36Sopenharmony_ci			"\n%s EQ info: EQ-STAT[max:x%x noE:x%x "
401262306a36Sopenharmony_ci			"cqe_proc:x%x eqe_proc:x%llx eqd %d]\n",
401362306a36Sopenharmony_ci			eqtype, qp->q_cnt_1, qp->q_cnt_2, qp->q_cnt_3,
401462306a36Sopenharmony_ci			(unsigned long long)qp->q_cnt_4, qp->q_mode);
401562306a36Sopenharmony_ci	len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
401662306a36Sopenharmony_ci			"EQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
401762306a36Sopenharmony_ci			"HST-IDX[%04d], NTFI[%03d], PLMT[%03d], AFFIN[%03d]",
401862306a36Sopenharmony_ci			qp->queue_id, qp->entry_count, qp->entry_size,
401962306a36Sopenharmony_ci			qp->host_index, qp->notify_interval,
402062306a36Sopenharmony_ci			qp->max_proc_limit, qp->chann);
402162306a36Sopenharmony_ci	len +=  scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
402262306a36Sopenharmony_ci			"\n");
402362306a36Sopenharmony_ci
402462306a36Sopenharmony_ci	return len;
402562306a36Sopenharmony_ci}
402662306a36Sopenharmony_ci
402762306a36Sopenharmony_ci/**
402862306a36Sopenharmony_ci * lpfc_idiag_queinfo_read - idiag debugfs read queue information
402962306a36Sopenharmony_ci * @file: The file pointer to read from.
403062306a36Sopenharmony_ci * @buf: The buffer to copy the data to.
403162306a36Sopenharmony_ci * @nbytes: The number of bytes to read.
403262306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
403362306a36Sopenharmony_ci *
403462306a36Sopenharmony_ci * Description:
403562306a36Sopenharmony_ci * This routine reads data from the @phba SLI4 PCI function queue information,
403662306a36Sopenharmony_ci * and copies to user @buf.
403762306a36Sopenharmony_ci * This routine only returns 1 EQs worth of information. It remembers the last
403862306a36Sopenharmony_ci * EQ read and jumps to the next EQ. Thus subsequent calls to queInfo will
403962306a36Sopenharmony_ci * retrieve all EQs allocated for the phba.
404062306a36Sopenharmony_ci *
404162306a36Sopenharmony_ci * Returns:
404262306a36Sopenharmony_ci * This function returns the amount of data that was read (this could be less
404362306a36Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value.
404462306a36Sopenharmony_ci **/
404562306a36Sopenharmony_cistatic ssize_t
404662306a36Sopenharmony_cilpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
404762306a36Sopenharmony_ci			loff_t *ppos)
404862306a36Sopenharmony_ci{
404962306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
405062306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
405162306a36Sopenharmony_ci	char *pbuffer;
405262306a36Sopenharmony_ci	int max_cnt, rc, x, len = 0;
405362306a36Sopenharmony_ci	struct lpfc_queue *qp = NULL;
405462306a36Sopenharmony_ci
405562306a36Sopenharmony_ci	if (!debug->buffer)
405662306a36Sopenharmony_ci		debug->buffer = kmalloc(LPFC_QUE_INFO_GET_BUF_SIZE, GFP_KERNEL);
405762306a36Sopenharmony_ci	if (!debug->buffer)
405862306a36Sopenharmony_ci		return 0;
405962306a36Sopenharmony_ci	pbuffer = debug->buffer;
406062306a36Sopenharmony_ci	max_cnt = LPFC_QUE_INFO_GET_BUF_SIZE - 256;
406162306a36Sopenharmony_ci
406262306a36Sopenharmony_ci	if (*ppos)
406362306a36Sopenharmony_ci		return 0;
406462306a36Sopenharmony_ci
406562306a36Sopenharmony_ci	spin_lock_irq(&phba->hbalock);
406662306a36Sopenharmony_ci
406762306a36Sopenharmony_ci	/* Fast-path event queue */
406862306a36Sopenharmony_ci	if (phba->sli4_hba.hdwq && phba->cfg_hdw_queue) {
406962306a36Sopenharmony_ci
407062306a36Sopenharmony_ci		x = phba->lpfc_idiag_last_eq;
407162306a36Sopenharmony_ci		phba->lpfc_idiag_last_eq++;
407262306a36Sopenharmony_ci		if (phba->lpfc_idiag_last_eq >= phba->cfg_hdw_queue)
407362306a36Sopenharmony_ci			phba->lpfc_idiag_last_eq = 0;
407462306a36Sopenharmony_ci
407562306a36Sopenharmony_ci		len += scnprintf(pbuffer + len,
407662306a36Sopenharmony_ci				 LPFC_QUE_INFO_GET_BUF_SIZE - len,
407762306a36Sopenharmony_ci				 "HDWQ %d out of %d HBA HDWQs\n",
407862306a36Sopenharmony_ci				 x, phba->cfg_hdw_queue);
407962306a36Sopenharmony_ci
408062306a36Sopenharmony_ci		/* Fast-path EQ */
408162306a36Sopenharmony_ci		qp = phba->sli4_hba.hdwq[x].hba_eq;
408262306a36Sopenharmony_ci		if (!qp)
408362306a36Sopenharmony_ci			goto out;
408462306a36Sopenharmony_ci
408562306a36Sopenharmony_ci		len = __lpfc_idiag_print_eq(qp, "HBA", pbuffer, len);
408662306a36Sopenharmony_ci
408762306a36Sopenharmony_ci		/* Reset max counter */
408862306a36Sopenharmony_ci		qp->EQ_max_eqe = 0;
408962306a36Sopenharmony_ci
409062306a36Sopenharmony_ci		if (len >= max_cnt)
409162306a36Sopenharmony_ci			goto too_big;
409262306a36Sopenharmony_ci
409362306a36Sopenharmony_ci		/* will dump both fcp and nvme cqs/wqs for the eq */
409462306a36Sopenharmony_ci		rc = lpfc_idiag_cqs_for_eq(phba, pbuffer, &len,
409562306a36Sopenharmony_ci			max_cnt, x, qp->queue_id);
409662306a36Sopenharmony_ci		if (rc)
409762306a36Sopenharmony_ci			goto too_big;
409862306a36Sopenharmony_ci
409962306a36Sopenharmony_ci		/* Only EQ 0 has slow path CQs configured */
410062306a36Sopenharmony_ci		if (x)
410162306a36Sopenharmony_ci			goto out;
410262306a36Sopenharmony_ci
410362306a36Sopenharmony_ci		/* Slow-path mailbox CQ */
410462306a36Sopenharmony_ci		qp = phba->sli4_hba.mbx_cq;
410562306a36Sopenharmony_ci		len = __lpfc_idiag_print_cq(qp, "MBX", pbuffer, len);
410662306a36Sopenharmony_ci		if (len >= max_cnt)
410762306a36Sopenharmony_ci			goto too_big;
410862306a36Sopenharmony_ci
410962306a36Sopenharmony_ci		/* Slow-path MBOX MQ */
411062306a36Sopenharmony_ci		qp = phba->sli4_hba.mbx_wq;
411162306a36Sopenharmony_ci		len = __lpfc_idiag_print_wq(qp, "MBX", pbuffer, len);
411262306a36Sopenharmony_ci		if (len >= max_cnt)
411362306a36Sopenharmony_ci			goto too_big;
411462306a36Sopenharmony_ci
411562306a36Sopenharmony_ci		/* Slow-path ELS response CQ */
411662306a36Sopenharmony_ci		qp = phba->sli4_hba.els_cq;
411762306a36Sopenharmony_ci		len = __lpfc_idiag_print_cq(qp, "ELS", pbuffer, len);
411862306a36Sopenharmony_ci		/* Reset max counter */
411962306a36Sopenharmony_ci		if (qp)
412062306a36Sopenharmony_ci			qp->CQ_max_cqe = 0;
412162306a36Sopenharmony_ci		if (len >= max_cnt)
412262306a36Sopenharmony_ci			goto too_big;
412362306a36Sopenharmony_ci
412462306a36Sopenharmony_ci		/* Slow-path ELS WQ */
412562306a36Sopenharmony_ci		qp = phba->sli4_hba.els_wq;
412662306a36Sopenharmony_ci		len = __lpfc_idiag_print_wq(qp, "ELS", pbuffer, len);
412762306a36Sopenharmony_ci		if (len >= max_cnt)
412862306a36Sopenharmony_ci			goto too_big;
412962306a36Sopenharmony_ci
413062306a36Sopenharmony_ci		qp = phba->sli4_hba.hdr_rq;
413162306a36Sopenharmony_ci		len = __lpfc_idiag_print_rqpair(qp, phba->sli4_hba.dat_rq,
413262306a36Sopenharmony_ci						"ELS RQpair", pbuffer, len);
413362306a36Sopenharmony_ci		if (len >= max_cnt)
413462306a36Sopenharmony_ci			goto too_big;
413562306a36Sopenharmony_ci
413662306a36Sopenharmony_ci		/* Slow-path NVME LS response CQ */
413762306a36Sopenharmony_ci		qp = phba->sli4_hba.nvmels_cq;
413862306a36Sopenharmony_ci		len = __lpfc_idiag_print_cq(qp, "NVME LS",
413962306a36Sopenharmony_ci						pbuffer, len);
414062306a36Sopenharmony_ci		/* Reset max counter */
414162306a36Sopenharmony_ci		if (qp)
414262306a36Sopenharmony_ci			qp->CQ_max_cqe = 0;
414362306a36Sopenharmony_ci		if (len >= max_cnt)
414462306a36Sopenharmony_ci			goto too_big;
414562306a36Sopenharmony_ci
414662306a36Sopenharmony_ci		/* Slow-path NVME LS WQ */
414762306a36Sopenharmony_ci		qp = phba->sli4_hba.nvmels_wq;
414862306a36Sopenharmony_ci		len = __lpfc_idiag_print_wq(qp, "NVME LS",
414962306a36Sopenharmony_ci						pbuffer, len);
415062306a36Sopenharmony_ci		if (len >= max_cnt)
415162306a36Sopenharmony_ci			goto too_big;
415262306a36Sopenharmony_ci
415362306a36Sopenharmony_ci		goto out;
415462306a36Sopenharmony_ci	}
415562306a36Sopenharmony_ci
415662306a36Sopenharmony_ci	spin_unlock_irq(&phba->hbalock);
415762306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
415862306a36Sopenharmony_ci
415962306a36Sopenharmony_citoo_big:
416062306a36Sopenharmony_ci	len +=  scnprintf(pbuffer + len,
416162306a36Sopenharmony_ci		LPFC_QUE_INFO_GET_BUF_SIZE - len, "Truncated ...\n");
416262306a36Sopenharmony_ciout:
416362306a36Sopenharmony_ci	spin_unlock_irq(&phba->hbalock);
416462306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
416562306a36Sopenharmony_ci}
416662306a36Sopenharmony_ci
416762306a36Sopenharmony_ci/**
416862306a36Sopenharmony_ci * lpfc_idiag_que_param_check - queue access command parameter sanity check
416962306a36Sopenharmony_ci * @q: The pointer to queue structure.
417062306a36Sopenharmony_ci * @index: The index into a queue entry.
417162306a36Sopenharmony_ci * @count: The number of queue entries to access.
417262306a36Sopenharmony_ci *
417362306a36Sopenharmony_ci * Description:
417462306a36Sopenharmony_ci * The routine performs sanity check on device queue access method commands.
417562306a36Sopenharmony_ci *
417662306a36Sopenharmony_ci * Returns:
417762306a36Sopenharmony_ci * This function returns -EINVAL when fails the sanity check, otherwise, it
417862306a36Sopenharmony_ci * returns 0.
417962306a36Sopenharmony_ci **/
418062306a36Sopenharmony_cistatic int
418162306a36Sopenharmony_cilpfc_idiag_que_param_check(struct lpfc_queue *q, int index, int count)
418262306a36Sopenharmony_ci{
418362306a36Sopenharmony_ci	/* Only support single entry read or browsing */
418462306a36Sopenharmony_ci	if ((count != 1) && (count != LPFC_QUE_ACC_BROWSE))
418562306a36Sopenharmony_ci		return -EINVAL;
418662306a36Sopenharmony_ci	if (index > q->entry_count - 1)
418762306a36Sopenharmony_ci		return -EINVAL;
418862306a36Sopenharmony_ci	return 0;
418962306a36Sopenharmony_ci}
419062306a36Sopenharmony_ci
419162306a36Sopenharmony_ci/**
419262306a36Sopenharmony_ci * lpfc_idiag_queacc_read_qe - read a single entry from the given queue index
419362306a36Sopenharmony_ci * @pbuffer: The pointer to buffer to copy the read data into.
419462306a36Sopenharmony_ci * @len: Length of the buffer.
419562306a36Sopenharmony_ci * @pque: The pointer to the queue to be read.
419662306a36Sopenharmony_ci * @index: The index into the queue entry.
419762306a36Sopenharmony_ci *
419862306a36Sopenharmony_ci * Description:
419962306a36Sopenharmony_ci * This routine reads out a single entry from the given queue's index location
420062306a36Sopenharmony_ci * and copies it into the buffer provided.
420162306a36Sopenharmony_ci *
420262306a36Sopenharmony_ci * Returns:
420362306a36Sopenharmony_ci * This function returns 0 when it fails, otherwise, it returns the length of
420462306a36Sopenharmony_ci * the data read into the buffer provided.
420562306a36Sopenharmony_ci **/
420662306a36Sopenharmony_cistatic int
420762306a36Sopenharmony_cilpfc_idiag_queacc_read_qe(char *pbuffer, int len, struct lpfc_queue *pque,
420862306a36Sopenharmony_ci			  uint32_t index)
420962306a36Sopenharmony_ci{
421062306a36Sopenharmony_ci	int offset, esize;
421162306a36Sopenharmony_ci	uint32_t *pentry;
421262306a36Sopenharmony_ci
421362306a36Sopenharmony_ci	if (!pbuffer || !pque)
421462306a36Sopenharmony_ci		return 0;
421562306a36Sopenharmony_ci
421662306a36Sopenharmony_ci	esize = pque->entry_size;
421762306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len,
421862306a36Sopenharmony_ci			"QE-INDEX[%04d]:\n", index);
421962306a36Sopenharmony_ci
422062306a36Sopenharmony_ci	offset = 0;
422162306a36Sopenharmony_ci	pentry = lpfc_sli4_qe(pque, index);
422262306a36Sopenharmony_ci	while (esize > 0) {
422362306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len,
422462306a36Sopenharmony_ci				"%08x ", *pentry);
422562306a36Sopenharmony_ci		pentry++;
422662306a36Sopenharmony_ci		offset += sizeof(uint32_t);
422762306a36Sopenharmony_ci		esize -= sizeof(uint32_t);
422862306a36Sopenharmony_ci		if (esize > 0 && !(offset % (4 * sizeof(uint32_t))))
422962306a36Sopenharmony_ci			len += scnprintf(pbuffer+len,
423062306a36Sopenharmony_ci					LPFC_QUE_ACC_BUF_SIZE-len, "\n");
423162306a36Sopenharmony_ci	}
423262306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, "\n");
423362306a36Sopenharmony_ci
423462306a36Sopenharmony_ci	return len;
423562306a36Sopenharmony_ci}
423662306a36Sopenharmony_ci
423762306a36Sopenharmony_ci/**
423862306a36Sopenharmony_ci * lpfc_idiag_queacc_read - idiag debugfs read port queue
423962306a36Sopenharmony_ci * @file: The file pointer to read from.
424062306a36Sopenharmony_ci * @buf: The buffer to copy the data to.
424162306a36Sopenharmony_ci * @nbytes: The number of bytes to read.
424262306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
424362306a36Sopenharmony_ci *
424462306a36Sopenharmony_ci * Description:
424562306a36Sopenharmony_ci * This routine reads data from the @phba device queue memory according to the
424662306a36Sopenharmony_ci * idiag command, and copies to user @buf. Depending on the queue dump read
424762306a36Sopenharmony_ci * command setup, it does either a single queue entry read or browing through
424862306a36Sopenharmony_ci * all entries of the queue.
424962306a36Sopenharmony_ci *
425062306a36Sopenharmony_ci * Returns:
425162306a36Sopenharmony_ci * This function returns the amount of data that was read (this could be less
425262306a36Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value.
425362306a36Sopenharmony_ci **/
425462306a36Sopenharmony_cistatic ssize_t
425562306a36Sopenharmony_cilpfc_idiag_queacc_read(struct file *file, char __user *buf, size_t nbytes,
425662306a36Sopenharmony_ci		       loff_t *ppos)
425762306a36Sopenharmony_ci{
425862306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
425962306a36Sopenharmony_ci	uint32_t last_index, index, count;
426062306a36Sopenharmony_ci	struct lpfc_queue *pque = NULL;
426162306a36Sopenharmony_ci	char *pbuffer;
426262306a36Sopenharmony_ci	int len = 0;
426362306a36Sopenharmony_ci
426462306a36Sopenharmony_ci	/* This is a user read operation */
426562306a36Sopenharmony_ci	debug->op = LPFC_IDIAG_OP_RD;
426662306a36Sopenharmony_ci
426762306a36Sopenharmony_ci	if (!debug->buffer)
426862306a36Sopenharmony_ci		debug->buffer = kmalloc(LPFC_QUE_ACC_BUF_SIZE, GFP_KERNEL);
426962306a36Sopenharmony_ci	if (!debug->buffer)
427062306a36Sopenharmony_ci		return 0;
427162306a36Sopenharmony_ci	pbuffer = debug->buffer;
427262306a36Sopenharmony_ci
427362306a36Sopenharmony_ci	if (*ppos)
427462306a36Sopenharmony_ci		return 0;
427562306a36Sopenharmony_ci
427662306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
427762306a36Sopenharmony_ci		index = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX];
427862306a36Sopenharmony_ci		count = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX];
427962306a36Sopenharmony_ci		pque = (struct lpfc_queue *)idiag.ptr_private;
428062306a36Sopenharmony_ci	} else
428162306a36Sopenharmony_ci		return 0;
428262306a36Sopenharmony_ci
428362306a36Sopenharmony_ci	/* Browse the queue starting from index */
428462306a36Sopenharmony_ci	if (count == LPFC_QUE_ACC_BROWSE)
428562306a36Sopenharmony_ci		goto que_browse;
428662306a36Sopenharmony_ci
428762306a36Sopenharmony_ci	/* Read a single entry from the queue */
428862306a36Sopenharmony_ci	len = lpfc_idiag_queacc_read_qe(pbuffer, len, pque, index);
428962306a36Sopenharmony_ci
429062306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
429162306a36Sopenharmony_ci
429262306a36Sopenharmony_cique_browse:
429362306a36Sopenharmony_ci
429462306a36Sopenharmony_ci	/* Browse all entries from the queue */
429562306a36Sopenharmony_ci	last_index = idiag.offset.last_rd;
429662306a36Sopenharmony_ci	index = last_index;
429762306a36Sopenharmony_ci
429862306a36Sopenharmony_ci	while (len < LPFC_QUE_ACC_SIZE - pque->entry_size) {
429962306a36Sopenharmony_ci		len = lpfc_idiag_queacc_read_qe(pbuffer, len, pque, index);
430062306a36Sopenharmony_ci		index++;
430162306a36Sopenharmony_ci		if (index > pque->entry_count - 1)
430262306a36Sopenharmony_ci			break;
430362306a36Sopenharmony_ci	}
430462306a36Sopenharmony_ci
430562306a36Sopenharmony_ci	/* Set up the offset for next portion of pci cfg read */
430662306a36Sopenharmony_ci	if (index > pque->entry_count - 1)
430762306a36Sopenharmony_ci		index = 0;
430862306a36Sopenharmony_ci	idiag.offset.last_rd = index;
430962306a36Sopenharmony_ci
431062306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
431162306a36Sopenharmony_ci}
431262306a36Sopenharmony_ci
431362306a36Sopenharmony_ci/**
431462306a36Sopenharmony_ci * lpfc_idiag_queacc_write - Syntax check and set up idiag queacc commands
431562306a36Sopenharmony_ci * @file: The file pointer to read from.
431662306a36Sopenharmony_ci * @buf: The buffer to copy the user data from.
431762306a36Sopenharmony_ci * @nbytes: The number of bytes to get.
431862306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
431962306a36Sopenharmony_ci *
432062306a36Sopenharmony_ci * This routine get the debugfs idiag command struct from user space and then
432162306a36Sopenharmony_ci * perform the syntax check for port queue read (dump) or write (set) command
432262306a36Sopenharmony_ci * accordingly. In the case of port queue read command, it sets up the command
432362306a36Sopenharmony_ci * in the idiag command struct for the following debugfs read operation. In
432462306a36Sopenharmony_ci * the case of port queue write operation, it executes the write operation
432562306a36Sopenharmony_ci * into the port queue entry accordingly.
432662306a36Sopenharmony_ci *
432762306a36Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful.
432862306a36Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user
432962306a36Sopenharmony_ci * space.
433062306a36Sopenharmony_ci **/
433162306a36Sopenharmony_cistatic ssize_t
433262306a36Sopenharmony_cilpfc_idiag_queacc_write(struct file *file, const char __user *buf,
433362306a36Sopenharmony_ci			size_t nbytes, loff_t *ppos)
433462306a36Sopenharmony_ci{
433562306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
433662306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
433762306a36Sopenharmony_ci	uint32_t qidx, quetp, queid, index, count, offset, value;
433862306a36Sopenharmony_ci	uint32_t *pentry;
433962306a36Sopenharmony_ci	struct lpfc_queue *pque, *qp;
434062306a36Sopenharmony_ci	int rc;
434162306a36Sopenharmony_ci
434262306a36Sopenharmony_ci	/* This is a user write operation */
434362306a36Sopenharmony_ci	debug->op = LPFC_IDIAG_OP_WR;
434462306a36Sopenharmony_ci
434562306a36Sopenharmony_ci	rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
434662306a36Sopenharmony_ci	if (rc < 0)
434762306a36Sopenharmony_ci		return rc;
434862306a36Sopenharmony_ci
434962306a36Sopenharmony_ci	/* Get and sanity check on command feilds */
435062306a36Sopenharmony_ci	quetp  = idiag.cmd.data[IDIAG_QUEACC_QUETP_INDX];
435162306a36Sopenharmony_ci	queid  = idiag.cmd.data[IDIAG_QUEACC_QUEID_INDX];
435262306a36Sopenharmony_ci	index  = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX];
435362306a36Sopenharmony_ci	count  = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX];
435462306a36Sopenharmony_ci	offset = idiag.cmd.data[IDIAG_QUEACC_OFFST_INDX];
435562306a36Sopenharmony_ci	value  = idiag.cmd.data[IDIAG_QUEACC_VALUE_INDX];
435662306a36Sopenharmony_ci
435762306a36Sopenharmony_ci	/* Sanity check on command line arguments */
435862306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR ||
435962306a36Sopenharmony_ci	    idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST ||
436062306a36Sopenharmony_ci	    idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL) {
436162306a36Sopenharmony_ci		if (rc != LPFC_QUE_ACC_WR_CMD_ARG)
436262306a36Sopenharmony_ci			goto error_out;
436362306a36Sopenharmony_ci		if (count != 1)
436462306a36Sopenharmony_ci			goto error_out;
436562306a36Sopenharmony_ci	} else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
436662306a36Sopenharmony_ci		if (rc != LPFC_QUE_ACC_RD_CMD_ARG)
436762306a36Sopenharmony_ci			goto error_out;
436862306a36Sopenharmony_ci	} else
436962306a36Sopenharmony_ci		goto error_out;
437062306a36Sopenharmony_ci
437162306a36Sopenharmony_ci	switch (quetp) {
437262306a36Sopenharmony_ci	case LPFC_IDIAG_EQ:
437362306a36Sopenharmony_ci		/* HBA event queue */
437462306a36Sopenharmony_ci		if (phba->sli4_hba.hdwq) {
437562306a36Sopenharmony_ci			for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) {
437662306a36Sopenharmony_ci				qp = phba->sli4_hba.hdwq[qidx].hba_eq;
437762306a36Sopenharmony_ci				if (qp && qp->queue_id == queid) {
437862306a36Sopenharmony_ci					/* Sanity check */
437962306a36Sopenharmony_ci					rc = lpfc_idiag_que_param_check(qp,
438062306a36Sopenharmony_ci						index, count);
438162306a36Sopenharmony_ci					if (rc)
438262306a36Sopenharmony_ci						goto error_out;
438362306a36Sopenharmony_ci					idiag.ptr_private = qp;
438462306a36Sopenharmony_ci					goto pass_check;
438562306a36Sopenharmony_ci				}
438662306a36Sopenharmony_ci			}
438762306a36Sopenharmony_ci		}
438862306a36Sopenharmony_ci		goto error_out;
438962306a36Sopenharmony_ci
439062306a36Sopenharmony_ci	case LPFC_IDIAG_CQ:
439162306a36Sopenharmony_ci		/* MBX complete queue */
439262306a36Sopenharmony_ci		if (phba->sli4_hba.mbx_cq &&
439362306a36Sopenharmony_ci		    phba->sli4_hba.mbx_cq->queue_id == queid) {
439462306a36Sopenharmony_ci			/* Sanity check */
439562306a36Sopenharmony_ci			rc = lpfc_idiag_que_param_check(
439662306a36Sopenharmony_ci					phba->sli4_hba.mbx_cq, index, count);
439762306a36Sopenharmony_ci			if (rc)
439862306a36Sopenharmony_ci				goto error_out;
439962306a36Sopenharmony_ci			idiag.ptr_private = phba->sli4_hba.mbx_cq;
440062306a36Sopenharmony_ci			goto pass_check;
440162306a36Sopenharmony_ci		}
440262306a36Sopenharmony_ci		/* ELS complete queue */
440362306a36Sopenharmony_ci		if (phba->sli4_hba.els_cq &&
440462306a36Sopenharmony_ci		    phba->sli4_hba.els_cq->queue_id == queid) {
440562306a36Sopenharmony_ci			/* Sanity check */
440662306a36Sopenharmony_ci			rc = lpfc_idiag_que_param_check(
440762306a36Sopenharmony_ci					phba->sli4_hba.els_cq, index, count);
440862306a36Sopenharmony_ci			if (rc)
440962306a36Sopenharmony_ci				goto error_out;
441062306a36Sopenharmony_ci			idiag.ptr_private = phba->sli4_hba.els_cq;
441162306a36Sopenharmony_ci			goto pass_check;
441262306a36Sopenharmony_ci		}
441362306a36Sopenharmony_ci		/* NVME LS complete queue */
441462306a36Sopenharmony_ci		if (phba->sli4_hba.nvmels_cq &&
441562306a36Sopenharmony_ci		    phba->sli4_hba.nvmels_cq->queue_id == queid) {
441662306a36Sopenharmony_ci			/* Sanity check */
441762306a36Sopenharmony_ci			rc = lpfc_idiag_que_param_check(
441862306a36Sopenharmony_ci					phba->sli4_hba.nvmels_cq, index, count);
441962306a36Sopenharmony_ci			if (rc)
442062306a36Sopenharmony_ci				goto error_out;
442162306a36Sopenharmony_ci			idiag.ptr_private = phba->sli4_hba.nvmels_cq;
442262306a36Sopenharmony_ci			goto pass_check;
442362306a36Sopenharmony_ci		}
442462306a36Sopenharmony_ci		/* FCP complete queue */
442562306a36Sopenharmony_ci		if (phba->sli4_hba.hdwq) {
442662306a36Sopenharmony_ci			for (qidx = 0; qidx < phba->cfg_hdw_queue;
442762306a36Sopenharmony_ci								qidx++) {
442862306a36Sopenharmony_ci				qp = phba->sli4_hba.hdwq[qidx].io_cq;
442962306a36Sopenharmony_ci				if (qp && qp->queue_id == queid) {
443062306a36Sopenharmony_ci					/* Sanity check */
443162306a36Sopenharmony_ci					rc = lpfc_idiag_que_param_check(
443262306a36Sopenharmony_ci						qp, index, count);
443362306a36Sopenharmony_ci					if (rc)
443462306a36Sopenharmony_ci						goto error_out;
443562306a36Sopenharmony_ci					idiag.ptr_private = qp;
443662306a36Sopenharmony_ci					goto pass_check;
443762306a36Sopenharmony_ci				}
443862306a36Sopenharmony_ci			}
443962306a36Sopenharmony_ci		}
444062306a36Sopenharmony_ci		goto error_out;
444162306a36Sopenharmony_ci
444262306a36Sopenharmony_ci	case LPFC_IDIAG_MQ:
444362306a36Sopenharmony_ci		/* MBX work queue */
444462306a36Sopenharmony_ci		if (phba->sli4_hba.mbx_wq &&
444562306a36Sopenharmony_ci		    phba->sli4_hba.mbx_wq->queue_id == queid) {
444662306a36Sopenharmony_ci			/* Sanity check */
444762306a36Sopenharmony_ci			rc = lpfc_idiag_que_param_check(
444862306a36Sopenharmony_ci					phba->sli4_hba.mbx_wq, index, count);
444962306a36Sopenharmony_ci			if (rc)
445062306a36Sopenharmony_ci				goto error_out;
445162306a36Sopenharmony_ci			idiag.ptr_private = phba->sli4_hba.mbx_wq;
445262306a36Sopenharmony_ci			goto pass_check;
445362306a36Sopenharmony_ci		}
445462306a36Sopenharmony_ci		goto error_out;
445562306a36Sopenharmony_ci
445662306a36Sopenharmony_ci	case LPFC_IDIAG_WQ:
445762306a36Sopenharmony_ci		/* ELS work queue */
445862306a36Sopenharmony_ci		if (phba->sli4_hba.els_wq &&
445962306a36Sopenharmony_ci		    phba->sli4_hba.els_wq->queue_id == queid) {
446062306a36Sopenharmony_ci			/* Sanity check */
446162306a36Sopenharmony_ci			rc = lpfc_idiag_que_param_check(
446262306a36Sopenharmony_ci					phba->sli4_hba.els_wq, index, count);
446362306a36Sopenharmony_ci			if (rc)
446462306a36Sopenharmony_ci				goto error_out;
446562306a36Sopenharmony_ci			idiag.ptr_private = phba->sli4_hba.els_wq;
446662306a36Sopenharmony_ci			goto pass_check;
446762306a36Sopenharmony_ci		}
446862306a36Sopenharmony_ci		/* NVME LS work queue */
446962306a36Sopenharmony_ci		if (phba->sli4_hba.nvmels_wq &&
447062306a36Sopenharmony_ci		    phba->sli4_hba.nvmels_wq->queue_id == queid) {
447162306a36Sopenharmony_ci			/* Sanity check */
447262306a36Sopenharmony_ci			rc = lpfc_idiag_que_param_check(
447362306a36Sopenharmony_ci					phba->sli4_hba.nvmels_wq, index, count);
447462306a36Sopenharmony_ci			if (rc)
447562306a36Sopenharmony_ci				goto error_out;
447662306a36Sopenharmony_ci			idiag.ptr_private = phba->sli4_hba.nvmels_wq;
447762306a36Sopenharmony_ci			goto pass_check;
447862306a36Sopenharmony_ci		}
447962306a36Sopenharmony_ci
448062306a36Sopenharmony_ci		if (phba->sli4_hba.hdwq) {
448162306a36Sopenharmony_ci			/* FCP/SCSI work queue */
448262306a36Sopenharmony_ci			for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) {
448362306a36Sopenharmony_ci				qp = phba->sli4_hba.hdwq[qidx].io_wq;
448462306a36Sopenharmony_ci				if (qp && qp->queue_id == queid) {
448562306a36Sopenharmony_ci					/* Sanity check */
448662306a36Sopenharmony_ci					rc = lpfc_idiag_que_param_check(
448762306a36Sopenharmony_ci						qp, index, count);
448862306a36Sopenharmony_ci					if (rc)
448962306a36Sopenharmony_ci						goto error_out;
449062306a36Sopenharmony_ci					idiag.ptr_private = qp;
449162306a36Sopenharmony_ci					goto pass_check;
449262306a36Sopenharmony_ci				}
449362306a36Sopenharmony_ci			}
449462306a36Sopenharmony_ci		}
449562306a36Sopenharmony_ci		goto error_out;
449662306a36Sopenharmony_ci
449762306a36Sopenharmony_ci	case LPFC_IDIAG_RQ:
449862306a36Sopenharmony_ci		/* HDR queue */
449962306a36Sopenharmony_ci		if (phba->sli4_hba.hdr_rq &&
450062306a36Sopenharmony_ci		    phba->sli4_hba.hdr_rq->queue_id == queid) {
450162306a36Sopenharmony_ci			/* Sanity check */
450262306a36Sopenharmony_ci			rc = lpfc_idiag_que_param_check(
450362306a36Sopenharmony_ci					phba->sli4_hba.hdr_rq, index, count);
450462306a36Sopenharmony_ci			if (rc)
450562306a36Sopenharmony_ci				goto error_out;
450662306a36Sopenharmony_ci			idiag.ptr_private = phba->sli4_hba.hdr_rq;
450762306a36Sopenharmony_ci			goto pass_check;
450862306a36Sopenharmony_ci		}
450962306a36Sopenharmony_ci		/* DAT queue */
451062306a36Sopenharmony_ci		if (phba->sli4_hba.dat_rq &&
451162306a36Sopenharmony_ci		    phba->sli4_hba.dat_rq->queue_id == queid) {
451262306a36Sopenharmony_ci			/* Sanity check */
451362306a36Sopenharmony_ci			rc = lpfc_idiag_que_param_check(
451462306a36Sopenharmony_ci					phba->sli4_hba.dat_rq, index, count);
451562306a36Sopenharmony_ci			if (rc)
451662306a36Sopenharmony_ci				goto error_out;
451762306a36Sopenharmony_ci			idiag.ptr_private = phba->sli4_hba.dat_rq;
451862306a36Sopenharmony_ci			goto pass_check;
451962306a36Sopenharmony_ci		}
452062306a36Sopenharmony_ci		goto error_out;
452162306a36Sopenharmony_ci	default:
452262306a36Sopenharmony_ci		goto error_out;
452362306a36Sopenharmony_ci	}
452462306a36Sopenharmony_ci
452562306a36Sopenharmony_cipass_check:
452662306a36Sopenharmony_ci
452762306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
452862306a36Sopenharmony_ci		if (count == LPFC_QUE_ACC_BROWSE)
452962306a36Sopenharmony_ci			idiag.offset.last_rd = index;
453062306a36Sopenharmony_ci	}
453162306a36Sopenharmony_ci
453262306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR ||
453362306a36Sopenharmony_ci	    idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST ||
453462306a36Sopenharmony_ci	    idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL) {
453562306a36Sopenharmony_ci		/* Additional sanity checks on write operation */
453662306a36Sopenharmony_ci		pque = (struct lpfc_queue *)idiag.ptr_private;
453762306a36Sopenharmony_ci		if (offset > pque->entry_size/sizeof(uint32_t) - 1)
453862306a36Sopenharmony_ci			goto error_out;
453962306a36Sopenharmony_ci		pentry = lpfc_sli4_qe(pque, index);
454062306a36Sopenharmony_ci		pentry += offset;
454162306a36Sopenharmony_ci		if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR)
454262306a36Sopenharmony_ci			*pentry = value;
454362306a36Sopenharmony_ci		if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST)
454462306a36Sopenharmony_ci			*pentry |= value;
454562306a36Sopenharmony_ci		if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL)
454662306a36Sopenharmony_ci			*pentry &= ~value;
454762306a36Sopenharmony_ci	}
454862306a36Sopenharmony_ci	return nbytes;
454962306a36Sopenharmony_ci
455062306a36Sopenharmony_cierror_out:
455162306a36Sopenharmony_ci	/* Clean out command structure on command error out */
455262306a36Sopenharmony_ci	memset(&idiag, 0, sizeof(idiag));
455362306a36Sopenharmony_ci	return -EINVAL;
455462306a36Sopenharmony_ci}
455562306a36Sopenharmony_ci
455662306a36Sopenharmony_ci/**
455762306a36Sopenharmony_ci * lpfc_idiag_drbacc_read_reg - idiag debugfs read a doorbell register
455862306a36Sopenharmony_ci * @phba: The pointer to hba structure.
455962306a36Sopenharmony_ci * @pbuffer: The pointer to the buffer to copy the data to.
456062306a36Sopenharmony_ci * @len: The length of bytes to copied.
456162306a36Sopenharmony_ci * @drbregid: The id to doorbell registers.
456262306a36Sopenharmony_ci *
456362306a36Sopenharmony_ci * Description:
456462306a36Sopenharmony_ci * This routine reads a doorbell register and copies its content to the
456562306a36Sopenharmony_ci * user buffer pointed to by @pbuffer.
456662306a36Sopenharmony_ci *
456762306a36Sopenharmony_ci * Returns:
456862306a36Sopenharmony_ci * This function returns the amount of data that was copied into @pbuffer.
456962306a36Sopenharmony_ci **/
457062306a36Sopenharmony_cistatic int
457162306a36Sopenharmony_cilpfc_idiag_drbacc_read_reg(struct lpfc_hba *phba, char *pbuffer,
457262306a36Sopenharmony_ci			   int len, uint32_t drbregid)
457362306a36Sopenharmony_ci{
457462306a36Sopenharmony_ci
457562306a36Sopenharmony_ci	if (!pbuffer)
457662306a36Sopenharmony_ci		return 0;
457762306a36Sopenharmony_ci
457862306a36Sopenharmony_ci	switch (drbregid) {
457962306a36Sopenharmony_ci	case LPFC_DRB_EQ:
458062306a36Sopenharmony_ci		len += scnprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE-len,
458162306a36Sopenharmony_ci				"EQ-DRB-REG: 0x%08x\n",
458262306a36Sopenharmony_ci				readl(phba->sli4_hba.EQDBregaddr));
458362306a36Sopenharmony_ci		break;
458462306a36Sopenharmony_ci	case LPFC_DRB_CQ:
458562306a36Sopenharmony_ci		len += scnprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE - len,
458662306a36Sopenharmony_ci				"CQ-DRB-REG: 0x%08x\n",
458762306a36Sopenharmony_ci				readl(phba->sli4_hba.CQDBregaddr));
458862306a36Sopenharmony_ci		break;
458962306a36Sopenharmony_ci	case LPFC_DRB_MQ:
459062306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
459162306a36Sopenharmony_ci				"MQ-DRB-REG:   0x%08x\n",
459262306a36Sopenharmony_ci				readl(phba->sli4_hba.MQDBregaddr));
459362306a36Sopenharmony_ci		break;
459462306a36Sopenharmony_ci	case LPFC_DRB_WQ:
459562306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
459662306a36Sopenharmony_ci				"WQ-DRB-REG:   0x%08x\n",
459762306a36Sopenharmony_ci				readl(phba->sli4_hba.WQDBregaddr));
459862306a36Sopenharmony_ci		break;
459962306a36Sopenharmony_ci	case LPFC_DRB_RQ:
460062306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
460162306a36Sopenharmony_ci				"RQ-DRB-REG:   0x%08x\n",
460262306a36Sopenharmony_ci				readl(phba->sli4_hba.RQDBregaddr));
460362306a36Sopenharmony_ci		break;
460462306a36Sopenharmony_ci	default:
460562306a36Sopenharmony_ci		break;
460662306a36Sopenharmony_ci	}
460762306a36Sopenharmony_ci
460862306a36Sopenharmony_ci	return len;
460962306a36Sopenharmony_ci}
461062306a36Sopenharmony_ci
461162306a36Sopenharmony_ci/**
461262306a36Sopenharmony_ci * lpfc_idiag_drbacc_read - idiag debugfs read port doorbell
461362306a36Sopenharmony_ci * @file: The file pointer to read from.
461462306a36Sopenharmony_ci * @buf: The buffer to copy the data to.
461562306a36Sopenharmony_ci * @nbytes: The number of bytes to read.
461662306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
461762306a36Sopenharmony_ci *
461862306a36Sopenharmony_ci * Description:
461962306a36Sopenharmony_ci * This routine reads data from the @phba device doorbell register according
462062306a36Sopenharmony_ci * to the idiag command, and copies to user @buf. Depending on the doorbell
462162306a36Sopenharmony_ci * register read command setup, it does either a single doorbell register
462262306a36Sopenharmony_ci * read or dump all doorbell registers.
462362306a36Sopenharmony_ci *
462462306a36Sopenharmony_ci * Returns:
462562306a36Sopenharmony_ci * This function returns the amount of data that was read (this could be less
462662306a36Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value.
462762306a36Sopenharmony_ci **/
462862306a36Sopenharmony_cistatic ssize_t
462962306a36Sopenharmony_cilpfc_idiag_drbacc_read(struct file *file, char __user *buf, size_t nbytes,
463062306a36Sopenharmony_ci		       loff_t *ppos)
463162306a36Sopenharmony_ci{
463262306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
463362306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
463462306a36Sopenharmony_ci	uint32_t drb_reg_id, i;
463562306a36Sopenharmony_ci	char *pbuffer;
463662306a36Sopenharmony_ci	int len = 0;
463762306a36Sopenharmony_ci
463862306a36Sopenharmony_ci	/* This is a user read operation */
463962306a36Sopenharmony_ci	debug->op = LPFC_IDIAG_OP_RD;
464062306a36Sopenharmony_ci
464162306a36Sopenharmony_ci	if (!debug->buffer)
464262306a36Sopenharmony_ci		debug->buffer = kmalloc(LPFC_DRB_ACC_BUF_SIZE, GFP_KERNEL);
464362306a36Sopenharmony_ci	if (!debug->buffer)
464462306a36Sopenharmony_ci		return 0;
464562306a36Sopenharmony_ci	pbuffer = debug->buffer;
464662306a36Sopenharmony_ci
464762306a36Sopenharmony_ci	if (*ppos)
464862306a36Sopenharmony_ci		return 0;
464962306a36Sopenharmony_ci
465062306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD)
465162306a36Sopenharmony_ci		drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX];
465262306a36Sopenharmony_ci	else
465362306a36Sopenharmony_ci		return 0;
465462306a36Sopenharmony_ci
465562306a36Sopenharmony_ci	if (drb_reg_id == LPFC_DRB_ACC_ALL)
465662306a36Sopenharmony_ci		for (i = 1; i <= LPFC_DRB_MAX; i++)
465762306a36Sopenharmony_ci			len = lpfc_idiag_drbacc_read_reg(phba,
465862306a36Sopenharmony_ci							 pbuffer, len, i);
465962306a36Sopenharmony_ci	else
466062306a36Sopenharmony_ci		len = lpfc_idiag_drbacc_read_reg(phba,
466162306a36Sopenharmony_ci						 pbuffer, len, drb_reg_id);
466262306a36Sopenharmony_ci
466362306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
466462306a36Sopenharmony_ci}
466562306a36Sopenharmony_ci
466662306a36Sopenharmony_ci/**
466762306a36Sopenharmony_ci * lpfc_idiag_drbacc_write - Syntax check and set up idiag drbacc commands
466862306a36Sopenharmony_ci * @file: The file pointer to read from.
466962306a36Sopenharmony_ci * @buf: The buffer to copy the user data from.
467062306a36Sopenharmony_ci * @nbytes: The number of bytes to get.
467162306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
467262306a36Sopenharmony_ci *
467362306a36Sopenharmony_ci * This routine get the debugfs idiag command struct from user space and then
467462306a36Sopenharmony_ci * perform the syntax check for port doorbell register read (dump) or write
467562306a36Sopenharmony_ci * (set) command accordingly. In the case of port queue read command, it sets
467662306a36Sopenharmony_ci * up the command in the idiag command struct for the following debugfs read
467762306a36Sopenharmony_ci * operation. In the case of port doorbell register write operation, it
467862306a36Sopenharmony_ci * executes the write operation into the port doorbell register accordingly.
467962306a36Sopenharmony_ci *
468062306a36Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful.
468162306a36Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user
468262306a36Sopenharmony_ci * space.
468362306a36Sopenharmony_ci **/
468462306a36Sopenharmony_cistatic ssize_t
468562306a36Sopenharmony_cilpfc_idiag_drbacc_write(struct file *file, const char __user *buf,
468662306a36Sopenharmony_ci			size_t nbytes, loff_t *ppos)
468762306a36Sopenharmony_ci{
468862306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
468962306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
469062306a36Sopenharmony_ci	uint32_t drb_reg_id, value, reg_val = 0;
469162306a36Sopenharmony_ci	void __iomem *drb_reg;
469262306a36Sopenharmony_ci	int rc;
469362306a36Sopenharmony_ci
469462306a36Sopenharmony_ci	/* This is a user write operation */
469562306a36Sopenharmony_ci	debug->op = LPFC_IDIAG_OP_WR;
469662306a36Sopenharmony_ci
469762306a36Sopenharmony_ci	rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
469862306a36Sopenharmony_ci	if (rc < 0)
469962306a36Sopenharmony_ci		return rc;
470062306a36Sopenharmony_ci
470162306a36Sopenharmony_ci	/* Sanity check on command line arguments */
470262306a36Sopenharmony_ci	drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX];
470362306a36Sopenharmony_ci	value = idiag.cmd.data[IDIAG_DRBACC_VALUE_INDX];
470462306a36Sopenharmony_ci
470562306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR ||
470662306a36Sopenharmony_ci	    idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST ||
470762306a36Sopenharmony_ci	    idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) {
470862306a36Sopenharmony_ci		if (rc != LPFC_DRB_ACC_WR_CMD_ARG)
470962306a36Sopenharmony_ci			goto error_out;
471062306a36Sopenharmony_ci		if (drb_reg_id > LPFC_DRB_MAX)
471162306a36Sopenharmony_ci			goto error_out;
471262306a36Sopenharmony_ci	} else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD) {
471362306a36Sopenharmony_ci		if (rc != LPFC_DRB_ACC_RD_CMD_ARG)
471462306a36Sopenharmony_ci			goto error_out;
471562306a36Sopenharmony_ci		if ((drb_reg_id > LPFC_DRB_MAX) &&
471662306a36Sopenharmony_ci		    (drb_reg_id != LPFC_DRB_ACC_ALL))
471762306a36Sopenharmony_ci			goto error_out;
471862306a36Sopenharmony_ci	} else
471962306a36Sopenharmony_ci		goto error_out;
472062306a36Sopenharmony_ci
472162306a36Sopenharmony_ci	/* Perform the write access operation */
472262306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR ||
472362306a36Sopenharmony_ci	    idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST ||
472462306a36Sopenharmony_ci	    idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) {
472562306a36Sopenharmony_ci		switch (drb_reg_id) {
472662306a36Sopenharmony_ci		case LPFC_DRB_EQ:
472762306a36Sopenharmony_ci			drb_reg = phba->sli4_hba.EQDBregaddr;
472862306a36Sopenharmony_ci			break;
472962306a36Sopenharmony_ci		case LPFC_DRB_CQ:
473062306a36Sopenharmony_ci			drb_reg = phba->sli4_hba.CQDBregaddr;
473162306a36Sopenharmony_ci			break;
473262306a36Sopenharmony_ci		case LPFC_DRB_MQ:
473362306a36Sopenharmony_ci			drb_reg = phba->sli4_hba.MQDBregaddr;
473462306a36Sopenharmony_ci			break;
473562306a36Sopenharmony_ci		case LPFC_DRB_WQ:
473662306a36Sopenharmony_ci			drb_reg = phba->sli4_hba.WQDBregaddr;
473762306a36Sopenharmony_ci			break;
473862306a36Sopenharmony_ci		case LPFC_DRB_RQ:
473962306a36Sopenharmony_ci			drb_reg = phba->sli4_hba.RQDBregaddr;
474062306a36Sopenharmony_ci			break;
474162306a36Sopenharmony_ci		default:
474262306a36Sopenharmony_ci			goto error_out;
474362306a36Sopenharmony_ci		}
474462306a36Sopenharmony_ci
474562306a36Sopenharmony_ci		if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR)
474662306a36Sopenharmony_ci			reg_val = value;
474762306a36Sopenharmony_ci		if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST) {
474862306a36Sopenharmony_ci			reg_val = readl(drb_reg);
474962306a36Sopenharmony_ci			reg_val |= value;
475062306a36Sopenharmony_ci		}
475162306a36Sopenharmony_ci		if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) {
475262306a36Sopenharmony_ci			reg_val = readl(drb_reg);
475362306a36Sopenharmony_ci			reg_val &= ~value;
475462306a36Sopenharmony_ci		}
475562306a36Sopenharmony_ci		writel(reg_val, drb_reg);
475662306a36Sopenharmony_ci		readl(drb_reg); /* flush */
475762306a36Sopenharmony_ci	}
475862306a36Sopenharmony_ci	return nbytes;
475962306a36Sopenharmony_ci
476062306a36Sopenharmony_cierror_out:
476162306a36Sopenharmony_ci	/* Clean out command structure on command error out */
476262306a36Sopenharmony_ci	memset(&idiag, 0, sizeof(idiag));
476362306a36Sopenharmony_ci	return -EINVAL;
476462306a36Sopenharmony_ci}
476562306a36Sopenharmony_ci
476662306a36Sopenharmony_ci/**
476762306a36Sopenharmony_ci * lpfc_idiag_ctlacc_read_reg - idiag debugfs read a control registers
476862306a36Sopenharmony_ci * @phba: The pointer to hba structure.
476962306a36Sopenharmony_ci * @pbuffer: The pointer to the buffer to copy the data to.
477062306a36Sopenharmony_ci * @len: The length of bytes to copied.
477162306a36Sopenharmony_ci * @ctlregid: The id to doorbell registers.
477262306a36Sopenharmony_ci *
477362306a36Sopenharmony_ci * Description:
477462306a36Sopenharmony_ci * This routine reads a control register and copies its content to the
477562306a36Sopenharmony_ci * user buffer pointed to by @pbuffer.
477662306a36Sopenharmony_ci *
477762306a36Sopenharmony_ci * Returns:
477862306a36Sopenharmony_ci * This function returns the amount of data that was copied into @pbuffer.
477962306a36Sopenharmony_ci **/
478062306a36Sopenharmony_cistatic int
478162306a36Sopenharmony_cilpfc_idiag_ctlacc_read_reg(struct lpfc_hba *phba, char *pbuffer,
478262306a36Sopenharmony_ci			   int len, uint32_t ctlregid)
478362306a36Sopenharmony_ci{
478462306a36Sopenharmony_ci
478562306a36Sopenharmony_ci	if (!pbuffer)
478662306a36Sopenharmony_ci		return 0;
478762306a36Sopenharmony_ci
478862306a36Sopenharmony_ci	switch (ctlregid) {
478962306a36Sopenharmony_ci	case LPFC_CTL_PORT_SEM:
479062306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
479162306a36Sopenharmony_ci				"Port SemReg:   0x%08x\n",
479262306a36Sopenharmony_ci				readl(phba->sli4_hba.conf_regs_memmap_p +
479362306a36Sopenharmony_ci				      LPFC_CTL_PORT_SEM_OFFSET));
479462306a36Sopenharmony_ci		break;
479562306a36Sopenharmony_ci	case LPFC_CTL_PORT_STA:
479662306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
479762306a36Sopenharmony_ci				"Port StaReg:   0x%08x\n",
479862306a36Sopenharmony_ci				readl(phba->sli4_hba.conf_regs_memmap_p +
479962306a36Sopenharmony_ci				      LPFC_CTL_PORT_STA_OFFSET));
480062306a36Sopenharmony_ci		break;
480162306a36Sopenharmony_ci	case LPFC_CTL_PORT_CTL:
480262306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
480362306a36Sopenharmony_ci				"Port CtlReg:   0x%08x\n",
480462306a36Sopenharmony_ci				readl(phba->sli4_hba.conf_regs_memmap_p +
480562306a36Sopenharmony_ci				      LPFC_CTL_PORT_CTL_OFFSET));
480662306a36Sopenharmony_ci		break;
480762306a36Sopenharmony_ci	case LPFC_CTL_PORT_ER1:
480862306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
480962306a36Sopenharmony_ci				"Port Er1Reg:   0x%08x\n",
481062306a36Sopenharmony_ci				readl(phba->sli4_hba.conf_regs_memmap_p +
481162306a36Sopenharmony_ci				      LPFC_CTL_PORT_ER1_OFFSET));
481262306a36Sopenharmony_ci		break;
481362306a36Sopenharmony_ci	case LPFC_CTL_PORT_ER2:
481462306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
481562306a36Sopenharmony_ci				"Port Er2Reg:   0x%08x\n",
481662306a36Sopenharmony_ci				readl(phba->sli4_hba.conf_regs_memmap_p +
481762306a36Sopenharmony_ci				      LPFC_CTL_PORT_ER2_OFFSET));
481862306a36Sopenharmony_ci		break;
481962306a36Sopenharmony_ci	case LPFC_CTL_PDEV_CTL:
482062306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
482162306a36Sopenharmony_ci				"PDev CtlReg:   0x%08x\n",
482262306a36Sopenharmony_ci				readl(phba->sli4_hba.conf_regs_memmap_p +
482362306a36Sopenharmony_ci				      LPFC_CTL_PDEV_CTL_OFFSET));
482462306a36Sopenharmony_ci		break;
482562306a36Sopenharmony_ci	default:
482662306a36Sopenharmony_ci		break;
482762306a36Sopenharmony_ci	}
482862306a36Sopenharmony_ci	return len;
482962306a36Sopenharmony_ci}
483062306a36Sopenharmony_ci
483162306a36Sopenharmony_ci/**
483262306a36Sopenharmony_ci * lpfc_idiag_ctlacc_read - idiag debugfs read port and device control register
483362306a36Sopenharmony_ci * @file: The file pointer to read from.
483462306a36Sopenharmony_ci * @buf: The buffer to copy the data to.
483562306a36Sopenharmony_ci * @nbytes: The number of bytes to read.
483662306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
483762306a36Sopenharmony_ci *
483862306a36Sopenharmony_ci * Description:
483962306a36Sopenharmony_ci * This routine reads data from the @phba port and device registers according
484062306a36Sopenharmony_ci * to the idiag command, and copies to user @buf.
484162306a36Sopenharmony_ci *
484262306a36Sopenharmony_ci * Returns:
484362306a36Sopenharmony_ci * This function returns the amount of data that was read (this could be less
484462306a36Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value.
484562306a36Sopenharmony_ci **/
484662306a36Sopenharmony_cistatic ssize_t
484762306a36Sopenharmony_cilpfc_idiag_ctlacc_read(struct file *file, char __user *buf, size_t nbytes,
484862306a36Sopenharmony_ci		       loff_t *ppos)
484962306a36Sopenharmony_ci{
485062306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
485162306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
485262306a36Sopenharmony_ci	uint32_t ctl_reg_id, i;
485362306a36Sopenharmony_ci	char *pbuffer;
485462306a36Sopenharmony_ci	int len = 0;
485562306a36Sopenharmony_ci
485662306a36Sopenharmony_ci	/* This is a user read operation */
485762306a36Sopenharmony_ci	debug->op = LPFC_IDIAG_OP_RD;
485862306a36Sopenharmony_ci
485962306a36Sopenharmony_ci	if (!debug->buffer)
486062306a36Sopenharmony_ci		debug->buffer = kmalloc(LPFC_CTL_ACC_BUF_SIZE, GFP_KERNEL);
486162306a36Sopenharmony_ci	if (!debug->buffer)
486262306a36Sopenharmony_ci		return 0;
486362306a36Sopenharmony_ci	pbuffer = debug->buffer;
486462306a36Sopenharmony_ci
486562306a36Sopenharmony_ci	if (*ppos)
486662306a36Sopenharmony_ci		return 0;
486762306a36Sopenharmony_ci
486862306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD)
486962306a36Sopenharmony_ci		ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX];
487062306a36Sopenharmony_ci	else
487162306a36Sopenharmony_ci		return 0;
487262306a36Sopenharmony_ci
487362306a36Sopenharmony_ci	if (ctl_reg_id == LPFC_CTL_ACC_ALL)
487462306a36Sopenharmony_ci		for (i = 1; i <= LPFC_CTL_MAX; i++)
487562306a36Sopenharmony_ci			len = lpfc_idiag_ctlacc_read_reg(phba,
487662306a36Sopenharmony_ci							 pbuffer, len, i);
487762306a36Sopenharmony_ci	else
487862306a36Sopenharmony_ci		len = lpfc_idiag_ctlacc_read_reg(phba,
487962306a36Sopenharmony_ci						 pbuffer, len, ctl_reg_id);
488062306a36Sopenharmony_ci
488162306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
488262306a36Sopenharmony_ci}
488362306a36Sopenharmony_ci
488462306a36Sopenharmony_ci/**
488562306a36Sopenharmony_ci * lpfc_idiag_ctlacc_write - Syntax check and set up idiag ctlacc commands
488662306a36Sopenharmony_ci * @file: The file pointer to read from.
488762306a36Sopenharmony_ci * @buf: The buffer to copy the user data from.
488862306a36Sopenharmony_ci * @nbytes: The number of bytes to get.
488962306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
489062306a36Sopenharmony_ci *
489162306a36Sopenharmony_ci * This routine get the debugfs idiag command struct from user space and then
489262306a36Sopenharmony_ci * perform the syntax check for port and device control register read (dump)
489362306a36Sopenharmony_ci * or write (set) command accordingly.
489462306a36Sopenharmony_ci *
489562306a36Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful.
489662306a36Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user
489762306a36Sopenharmony_ci * space.
489862306a36Sopenharmony_ci **/
489962306a36Sopenharmony_cistatic ssize_t
490062306a36Sopenharmony_cilpfc_idiag_ctlacc_write(struct file *file, const char __user *buf,
490162306a36Sopenharmony_ci			size_t nbytes, loff_t *ppos)
490262306a36Sopenharmony_ci{
490362306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
490462306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
490562306a36Sopenharmony_ci	uint32_t ctl_reg_id, value, reg_val = 0;
490662306a36Sopenharmony_ci	void __iomem *ctl_reg;
490762306a36Sopenharmony_ci	int rc;
490862306a36Sopenharmony_ci
490962306a36Sopenharmony_ci	/* This is a user write operation */
491062306a36Sopenharmony_ci	debug->op = LPFC_IDIAG_OP_WR;
491162306a36Sopenharmony_ci
491262306a36Sopenharmony_ci	rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
491362306a36Sopenharmony_ci	if (rc < 0)
491462306a36Sopenharmony_ci		return rc;
491562306a36Sopenharmony_ci
491662306a36Sopenharmony_ci	/* Sanity check on command line arguments */
491762306a36Sopenharmony_ci	ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX];
491862306a36Sopenharmony_ci	value = idiag.cmd.data[IDIAG_CTLACC_VALUE_INDX];
491962306a36Sopenharmony_ci
492062306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR ||
492162306a36Sopenharmony_ci	    idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST ||
492262306a36Sopenharmony_ci	    idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
492362306a36Sopenharmony_ci		if (rc != LPFC_CTL_ACC_WR_CMD_ARG)
492462306a36Sopenharmony_ci			goto error_out;
492562306a36Sopenharmony_ci		if (ctl_reg_id > LPFC_CTL_MAX)
492662306a36Sopenharmony_ci			goto error_out;
492762306a36Sopenharmony_ci	} else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD) {
492862306a36Sopenharmony_ci		if (rc != LPFC_CTL_ACC_RD_CMD_ARG)
492962306a36Sopenharmony_ci			goto error_out;
493062306a36Sopenharmony_ci		if ((ctl_reg_id > LPFC_CTL_MAX) &&
493162306a36Sopenharmony_ci		    (ctl_reg_id != LPFC_CTL_ACC_ALL))
493262306a36Sopenharmony_ci			goto error_out;
493362306a36Sopenharmony_ci	} else
493462306a36Sopenharmony_ci		goto error_out;
493562306a36Sopenharmony_ci
493662306a36Sopenharmony_ci	/* Perform the write access operation */
493762306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR ||
493862306a36Sopenharmony_ci	    idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST ||
493962306a36Sopenharmony_ci	    idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
494062306a36Sopenharmony_ci		switch (ctl_reg_id) {
494162306a36Sopenharmony_ci		case LPFC_CTL_PORT_SEM:
494262306a36Sopenharmony_ci			ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
494362306a36Sopenharmony_ci					LPFC_CTL_PORT_SEM_OFFSET;
494462306a36Sopenharmony_ci			break;
494562306a36Sopenharmony_ci		case LPFC_CTL_PORT_STA:
494662306a36Sopenharmony_ci			ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
494762306a36Sopenharmony_ci					LPFC_CTL_PORT_STA_OFFSET;
494862306a36Sopenharmony_ci			break;
494962306a36Sopenharmony_ci		case LPFC_CTL_PORT_CTL:
495062306a36Sopenharmony_ci			ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
495162306a36Sopenharmony_ci					LPFC_CTL_PORT_CTL_OFFSET;
495262306a36Sopenharmony_ci			break;
495362306a36Sopenharmony_ci		case LPFC_CTL_PORT_ER1:
495462306a36Sopenharmony_ci			ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
495562306a36Sopenharmony_ci					LPFC_CTL_PORT_ER1_OFFSET;
495662306a36Sopenharmony_ci			break;
495762306a36Sopenharmony_ci		case LPFC_CTL_PORT_ER2:
495862306a36Sopenharmony_ci			ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
495962306a36Sopenharmony_ci					LPFC_CTL_PORT_ER2_OFFSET;
496062306a36Sopenharmony_ci			break;
496162306a36Sopenharmony_ci		case LPFC_CTL_PDEV_CTL:
496262306a36Sopenharmony_ci			ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
496362306a36Sopenharmony_ci					LPFC_CTL_PDEV_CTL_OFFSET;
496462306a36Sopenharmony_ci			break;
496562306a36Sopenharmony_ci		default:
496662306a36Sopenharmony_ci			goto error_out;
496762306a36Sopenharmony_ci		}
496862306a36Sopenharmony_ci
496962306a36Sopenharmony_ci		if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR)
497062306a36Sopenharmony_ci			reg_val = value;
497162306a36Sopenharmony_ci		if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST) {
497262306a36Sopenharmony_ci			reg_val = readl(ctl_reg);
497362306a36Sopenharmony_ci			reg_val |= value;
497462306a36Sopenharmony_ci		}
497562306a36Sopenharmony_ci		if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
497662306a36Sopenharmony_ci			reg_val = readl(ctl_reg);
497762306a36Sopenharmony_ci			reg_val &= ~value;
497862306a36Sopenharmony_ci		}
497962306a36Sopenharmony_ci		writel(reg_val, ctl_reg);
498062306a36Sopenharmony_ci		readl(ctl_reg); /* flush */
498162306a36Sopenharmony_ci	}
498262306a36Sopenharmony_ci	return nbytes;
498362306a36Sopenharmony_ci
498462306a36Sopenharmony_cierror_out:
498562306a36Sopenharmony_ci	/* Clean out command structure on command error out */
498662306a36Sopenharmony_ci	memset(&idiag, 0, sizeof(idiag));
498762306a36Sopenharmony_ci	return -EINVAL;
498862306a36Sopenharmony_ci}
498962306a36Sopenharmony_ci
499062306a36Sopenharmony_ci/**
499162306a36Sopenharmony_ci * lpfc_idiag_mbxacc_get_setup - idiag debugfs get mailbox access setup
499262306a36Sopenharmony_ci * @phba: Pointer to HBA context object.
499362306a36Sopenharmony_ci * @pbuffer: Pointer to data buffer.
499462306a36Sopenharmony_ci *
499562306a36Sopenharmony_ci * Description:
499662306a36Sopenharmony_ci * This routine gets the driver mailbox access debugfs setup information.
499762306a36Sopenharmony_ci *
499862306a36Sopenharmony_ci * Returns:
499962306a36Sopenharmony_ci * This function returns the amount of data that was read (this could be less
500062306a36Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value.
500162306a36Sopenharmony_ci **/
500262306a36Sopenharmony_cistatic int
500362306a36Sopenharmony_cilpfc_idiag_mbxacc_get_setup(struct lpfc_hba *phba, char *pbuffer)
500462306a36Sopenharmony_ci{
500562306a36Sopenharmony_ci	uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd;
500662306a36Sopenharmony_ci	int len = 0;
500762306a36Sopenharmony_ci
500862306a36Sopenharmony_ci	mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
500962306a36Sopenharmony_ci	mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
501062306a36Sopenharmony_ci	mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
501162306a36Sopenharmony_ci	mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
501262306a36Sopenharmony_ci
501362306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
501462306a36Sopenharmony_ci			"mbx_dump_map: 0x%08x\n", mbx_dump_map);
501562306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
501662306a36Sopenharmony_ci			"mbx_dump_cnt: %04d\n", mbx_dump_cnt);
501762306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
501862306a36Sopenharmony_ci			"mbx_word_cnt: %04d\n", mbx_word_cnt);
501962306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
502062306a36Sopenharmony_ci			"mbx_mbox_cmd: 0x%02x\n", mbx_mbox_cmd);
502162306a36Sopenharmony_ci
502262306a36Sopenharmony_ci	return len;
502362306a36Sopenharmony_ci}
502462306a36Sopenharmony_ci
502562306a36Sopenharmony_ci/**
502662306a36Sopenharmony_ci * lpfc_idiag_mbxacc_read - idiag debugfs read on mailbox access
502762306a36Sopenharmony_ci * @file: The file pointer to read from.
502862306a36Sopenharmony_ci * @buf: The buffer to copy the data to.
502962306a36Sopenharmony_ci * @nbytes: The number of bytes to read.
503062306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
503162306a36Sopenharmony_ci *
503262306a36Sopenharmony_ci * Description:
503362306a36Sopenharmony_ci * This routine reads data from the @phba driver mailbox access debugfs setup
503462306a36Sopenharmony_ci * information.
503562306a36Sopenharmony_ci *
503662306a36Sopenharmony_ci * Returns:
503762306a36Sopenharmony_ci * This function returns the amount of data that was read (this could be less
503862306a36Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value.
503962306a36Sopenharmony_ci **/
504062306a36Sopenharmony_cistatic ssize_t
504162306a36Sopenharmony_cilpfc_idiag_mbxacc_read(struct file *file, char __user *buf, size_t nbytes,
504262306a36Sopenharmony_ci		       loff_t *ppos)
504362306a36Sopenharmony_ci{
504462306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
504562306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
504662306a36Sopenharmony_ci	char *pbuffer;
504762306a36Sopenharmony_ci	int len = 0;
504862306a36Sopenharmony_ci
504962306a36Sopenharmony_ci	/* This is a user read operation */
505062306a36Sopenharmony_ci	debug->op = LPFC_IDIAG_OP_RD;
505162306a36Sopenharmony_ci
505262306a36Sopenharmony_ci	if (!debug->buffer)
505362306a36Sopenharmony_ci		debug->buffer = kmalloc(LPFC_MBX_ACC_BUF_SIZE, GFP_KERNEL);
505462306a36Sopenharmony_ci	if (!debug->buffer)
505562306a36Sopenharmony_ci		return 0;
505662306a36Sopenharmony_ci	pbuffer = debug->buffer;
505762306a36Sopenharmony_ci
505862306a36Sopenharmony_ci	if (*ppos)
505962306a36Sopenharmony_ci		return 0;
506062306a36Sopenharmony_ci
506162306a36Sopenharmony_ci	if ((idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP) &&
506262306a36Sopenharmony_ci	    (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP))
506362306a36Sopenharmony_ci		return 0;
506462306a36Sopenharmony_ci
506562306a36Sopenharmony_ci	len = lpfc_idiag_mbxacc_get_setup(phba, pbuffer);
506662306a36Sopenharmony_ci
506762306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
506862306a36Sopenharmony_ci}
506962306a36Sopenharmony_ci
507062306a36Sopenharmony_ci/**
507162306a36Sopenharmony_ci * lpfc_idiag_mbxacc_write - Syntax check and set up idiag mbxacc commands
507262306a36Sopenharmony_ci * @file: The file pointer to read from.
507362306a36Sopenharmony_ci * @buf: The buffer to copy the user data from.
507462306a36Sopenharmony_ci * @nbytes: The number of bytes to get.
507562306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
507662306a36Sopenharmony_ci *
507762306a36Sopenharmony_ci * This routine get the debugfs idiag command struct from user space and then
507862306a36Sopenharmony_ci * perform the syntax check for driver mailbox command (dump) and sets up the
507962306a36Sopenharmony_ci * necessary states in the idiag command struct accordingly.
508062306a36Sopenharmony_ci *
508162306a36Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful.
508262306a36Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user
508362306a36Sopenharmony_ci * space.
508462306a36Sopenharmony_ci **/
508562306a36Sopenharmony_cistatic ssize_t
508662306a36Sopenharmony_cilpfc_idiag_mbxacc_write(struct file *file, const char __user *buf,
508762306a36Sopenharmony_ci			size_t nbytes, loff_t *ppos)
508862306a36Sopenharmony_ci{
508962306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
509062306a36Sopenharmony_ci	uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd;
509162306a36Sopenharmony_ci	int rc;
509262306a36Sopenharmony_ci
509362306a36Sopenharmony_ci	/* This is a user write operation */
509462306a36Sopenharmony_ci	debug->op = LPFC_IDIAG_OP_WR;
509562306a36Sopenharmony_ci
509662306a36Sopenharmony_ci	rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
509762306a36Sopenharmony_ci	if (rc < 0)
509862306a36Sopenharmony_ci		return rc;
509962306a36Sopenharmony_ci
510062306a36Sopenharmony_ci	/* Sanity check on command line arguments */
510162306a36Sopenharmony_ci	mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
510262306a36Sopenharmony_ci	mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
510362306a36Sopenharmony_ci	mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
510462306a36Sopenharmony_ci	mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
510562306a36Sopenharmony_ci
510662306a36Sopenharmony_ci	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_MBXACC_DP) {
510762306a36Sopenharmony_ci		if (!(mbx_dump_map & LPFC_MBX_DMP_MBX_ALL))
510862306a36Sopenharmony_ci			goto error_out;
510962306a36Sopenharmony_ci		if ((mbx_dump_map & ~LPFC_MBX_DMP_MBX_ALL) &&
511062306a36Sopenharmony_ci		    (mbx_dump_map != LPFC_MBX_DMP_ALL))
511162306a36Sopenharmony_ci			goto error_out;
511262306a36Sopenharmony_ci		if (mbx_word_cnt > sizeof(MAILBOX_t))
511362306a36Sopenharmony_ci			goto error_out;
511462306a36Sopenharmony_ci	} else if (idiag.cmd.opcode == LPFC_IDIAG_BSG_MBXACC_DP) {
511562306a36Sopenharmony_ci		if (!(mbx_dump_map & LPFC_BSG_DMP_MBX_ALL))
511662306a36Sopenharmony_ci			goto error_out;
511762306a36Sopenharmony_ci		if ((mbx_dump_map & ~LPFC_BSG_DMP_MBX_ALL) &&
511862306a36Sopenharmony_ci		    (mbx_dump_map != LPFC_MBX_DMP_ALL))
511962306a36Sopenharmony_ci			goto error_out;
512062306a36Sopenharmony_ci		if (mbx_word_cnt > (BSG_MBOX_SIZE)/4)
512162306a36Sopenharmony_ci			goto error_out;
512262306a36Sopenharmony_ci		if (mbx_mbox_cmd != 0x9b)
512362306a36Sopenharmony_ci			goto error_out;
512462306a36Sopenharmony_ci	} else
512562306a36Sopenharmony_ci		goto error_out;
512662306a36Sopenharmony_ci
512762306a36Sopenharmony_ci	if (mbx_word_cnt == 0)
512862306a36Sopenharmony_ci		goto error_out;
512962306a36Sopenharmony_ci	if (rc != LPFC_MBX_DMP_ARG)
513062306a36Sopenharmony_ci		goto error_out;
513162306a36Sopenharmony_ci	if (mbx_mbox_cmd & ~0xff)
513262306a36Sopenharmony_ci		goto error_out;
513362306a36Sopenharmony_ci
513462306a36Sopenharmony_ci	/* condition for stop mailbox dump */
513562306a36Sopenharmony_ci	if (mbx_dump_cnt == 0)
513662306a36Sopenharmony_ci		goto reset_out;
513762306a36Sopenharmony_ci
513862306a36Sopenharmony_ci	return nbytes;
513962306a36Sopenharmony_ci
514062306a36Sopenharmony_cireset_out:
514162306a36Sopenharmony_ci	/* Clean out command structure on command error out */
514262306a36Sopenharmony_ci	memset(&idiag, 0, sizeof(idiag));
514362306a36Sopenharmony_ci	return nbytes;
514462306a36Sopenharmony_ci
514562306a36Sopenharmony_cierror_out:
514662306a36Sopenharmony_ci	/* Clean out command structure on command error out */
514762306a36Sopenharmony_ci	memset(&idiag, 0, sizeof(idiag));
514862306a36Sopenharmony_ci	return -EINVAL;
514962306a36Sopenharmony_ci}
515062306a36Sopenharmony_ci
515162306a36Sopenharmony_ci/**
515262306a36Sopenharmony_ci * lpfc_idiag_extacc_avail_get - get the available extents information
515362306a36Sopenharmony_ci * @phba: pointer to lpfc hba data structure.
515462306a36Sopenharmony_ci * @pbuffer: pointer to internal buffer.
515562306a36Sopenharmony_ci * @len: length into the internal buffer data has been copied.
515662306a36Sopenharmony_ci *
515762306a36Sopenharmony_ci * Description:
515862306a36Sopenharmony_ci * This routine is to get the available extent information.
515962306a36Sopenharmony_ci *
516062306a36Sopenharmony_ci * Returns:
516162306a36Sopenharmony_ci * overall length of the data read into the internal buffer.
516262306a36Sopenharmony_ci **/
516362306a36Sopenharmony_cistatic int
516462306a36Sopenharmony_cilpfc_idiag_extacc_avail_get(struct lpfc_hba *phba, char *pbuffer, int len)
516562306a36Sopenharmony_ci{
516662306a36Sopenharmony_ci	uint16_t ext_cnt = 0, ext_size = 0;
516762306a36Sopenharmony_ci
516862306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
516962306a36Sopenharmony_ci			"\nAvailable Extents Information:\n");
517062306a36Sopenharmony_ci
517162306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
517262306a36Sopenharmony_ci			"\tPort Available VPI extents: ");
517362306a36Sopenharmony_ci	lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VPI,
517462306a36Sopenharmony_ci				       &ext_cnt, &ext_size);
517562306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
517662306a36Sopenharmony_ci			"Count %3d, Size %3d\n", ext_cnt, ext_size);
517762306a36Sopenharmony_ci
517862306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
517962306a36Sopenharmony_ci			"\tPort Available VFI extents: ");
518062306a36Sopenharmony_ci	lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VFI,
518162306a36Sopenharmony_ci				       &ext_cnt, &ext_size);
518262306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
518362306a36Sopenharmony_ci			"Count %3d, Size %3d\n", ext_cnt, ext_size);
518462306a36Sopenharmony_ci
518562306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
518662306a36Sopenharmony_ci			"\tPort Available RPI extents: ");
518762306a36Sopenharmony_ci	lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_RPI,
518862306a36Sopenharmony_ci				       &ext_cnt, &ext_size);
518962306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
519062306a36Sopenharmony_ci			"Count %3d, Size %3d\n", ext_cnt, ext_size);
519162306a36Sopenharmony_ci
519262306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
519362306a36Sopenharmony_ci			"\tPort Available XRI extents: ");
519462306a36Sopenharmony_ci	lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_XRI,
519562306a36Sopenharmony_ci				       &ext_cnt, &ext_size);
519662306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
519762306a36Sopenharmony_ci			"Count %3d, Size %3d\n", ext_cnt, ext_size);
519862306a36Sopenharmony_ci
519962306a36Sopenharmony_ci	return len;
520062306a36Sopenharmony_ci}
520162306a36Sopenharmony_ci
520262306a36Sopenharmony_ci/**
520362306a36Sopenharmony_ci * lpfc_idiag_extacc_alloc_get - get the allocated extents information
520462306a36Sopenharmony_ci * @phba: pointer to lpfc hba data structure.
520562306a36Sopenharmony_ci * @pbuffer: pointer to internal buffer.
520662306a36Sopenharmony_ci * @len: length into the internal buffer data has been copied.
520762306a36Sopenharmony_ci *
520862306a36Sopenharmony_ci * Description:
520962306a36Sopenharmony_ci * This routine is to get the allocated extent information.
521062306a36Sopenharmony_ci *
521162306a36Sopenharmony_ci * Returns:
521262306a36Sopenharmony_ci * overall length of the data read into the internal buffer.
521362306a36Sopenharmony_ci **/
521462306a36Sopenharmony_cistatic int
521562306a36Sopenharmony_cilpfc_idiag_extacc_alloc_get(struct lpfc_hba *phba, char *pbuffer, int len)
521662306a36Sopenharmony_ci{
521762306a36Sopenharmony_ci	uint16_t ext_cnt, ext_size;
521862306a36Sopenharmony_ci	int rc;
521962306a36Sopenharmony_ci
522062306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
522162306a36Sopenharmony_ci			"\nAllocated Extents Information:\n");
522262306a36Sopenharmony_ci
522362306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
522462306a36Sopenharmony_ci			"\tHost Allocated VPI extents: ");
522562306a36Sopenharmony_ci	rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VPI,
522662306a36Sopenharmony_ci					    &ext_cnt, &ext_size);
522762306a36Sopenharmony_ci	if (!rc)
522862306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
522962306a36Sopenharmony_ci				"Port %d Extent %3d, Size %3d\n",
523062306a36Sopenharmony_ci				phba->brd_no, ext_cnt, ext_size);
523162306a36Sopenharmony_ci	else
523262306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
523362306a36Sopenharmony_ci				"N/A\n");
523462306a36Sopenharmony_ci
523562306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
523662306a36Sopenharmony_ci			"\tHost Allocated VFI extents: ");
523762306a36Sopenharmony_ci	rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VFI,
523862306a36Sopenharmony_ci					    &ext_cnt, &ext_size);
523962306a36Sopenharmony_ci	if (!rc)
524062306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
524162306a36Sopenharmony_ci				"Port %d Extent %3d, Size %3d\n",
524262306a36Sopenharmony_ci				phba->brd_no, ext_cnt, ext_size);
524362306a36Sopenharmony_ci	else
524462306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
524562306a36Sopenharmony_ci				"N/A\n");
524662306a36Sopenharmony_ci
524762306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
524862306a36Sopenharmony_ci			"\tHost Allocated RPI extents: ");
524962306a36Sopenharmony_ci	rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_RPI,
525062306a36Sopenharmony_ci					    &ext_cnt, &ext_size);
525162306a36Sopenharmony_ci	if (!rc)
525262306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
525362306a36Sopenharmony_ci				"Port %d Extent %3d, Size %3d\n",
525462306a36Sopenharmony_ci				phba->brd_no, ext_cnt, ext_size);
525562306a36Sopenharmony_ci	else
525662306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
525762306a36Sopenharmony_ci				"N/A\n");
525862306a36Sopenharmony_ci
525962306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
526062306a36Sopenharmony_ci			"\tHost Allocated XRI extents: ");
526162306a36Sopenharmony_ci	rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_XRI,
526262306a36Sopenharmony_ci					    &ext_cnt, &ext_size);
526362306a36Sopenharmony_ci	if (!rc)
526462306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
526562306a36Sopenharmony_ci				"Port %d Extent %3d, Size %3d\n",
526662306a36Sopenharmony_ci				phba->brd_no, ext_cnt, ext_size);
526762306a36Sopenharmony_ci	else
526862306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
526962306a36Sopenharmony_ci				"N/A\n");
527062306a36Sopenharmony_ci
527162306a36Sopenharmony_ci	return len;
527262306a36Sopenharmony_ci}
527362306a36Sopenharmony_ci
527462306a36Sopenharmony_ci/**
527562306a36Sopenharmony_ci * lpfc_idiag_extacc_drivr_get - get driver extent information
527662306a36Sopenharmony_ci * @phba: pointer to lpfc hba data structure.
527762306a36Sopenharmony_ci * @pbuffer: pointer to internal buffer.
527862306a36Sopenharmony_ci * @len: length into the internal buffer data has been copied.
527962306a36Sopenharmony_ci *
528062306a36Sopenharmony_ci * Description:
528162306a36Sopenharmony_ci * This routine is to get the driver extent information.
528262306a36Sopenharmony_ci *
528362306a36Sopenharmony_ci * Returns:
528462306a36Sopenharmony_ci * overall length of the data read into the internal buffer.
528562306a36Sopenharmony_ci **/
528662306a36Sopenharmony_cistatic int
528762306a36Sopenharmony_cilpfc_idiag_extacc_drivr_get(struct lpfc_hba *phba, char *pbuffer, int len)
528862306a36Sopenharmony_ci{
528962306a36Sopenharmony_ci	struct lpfc_rsrc_blks *rsrc_blks;
529062306a36Sopenharmony_ci	int index;
529162306a36Sopenharmony_ci
529262306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
529362306a36Sopenharmony_ci			"\nDriver Extents Information:\n");
529462306a36Sopenharmony_ci
529562306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
529662306a36Sopenharmony_ci			"\tVPI extents:\n");
529762306a36Sopenharmony_ci	index = 0;
529862306a36Sopenharmony_ci	list_for_each_entry(rsrc_blks, &phba->lpfc_vpi_blk_list, list) {
529962306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
530062306a36Sopenharmony_ci				"\t\tBlock %3d: Start %4d, Count %4d\n",
530162306a36Sopenharmony_ci				index, rsrc_blks->rsrc_start,
530262306a36Sopenharmony_ci				rsrc_blks->rsrc_size);
530362306a36Sopenharmony_ci		index++;
530462306a36Sopenharmony_ci	}
530562306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
530662306a36Sopenharmony_ci			"\tVFI extents:\n");
530762306a36Sopenharmony_ci	index = 0;
530862306a36Sopenharmony_ci	list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_vfi_blk_list,
530962306a36Sopenharmony_ci			    list) {
531062306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
531162306a36Sopenharmony_ci				"\t\tBlock %3d: Start %4d, Count %4d\n",
531262306a36Sopenharmony_ci				index, rsrc_blks->rsrc_start,
531362306a36Sopenharmony_ci				rsrc_blks->rsrc_size);
531462306a36Sopenharmony_ci		index++;
531562306a36Sopenharmony_ci	}
531662306a36Sopenharmony_ci
531762306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
531862306a36Sopenharmony_ci			"\tRPI extents:\n");
531962306a36Sopenharmony_ci	index = 0;
532062306a36Sopenharmony_ci	list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_rpi_blk_list,
532162306a36Sopenharmony_ci			    list) {
532262306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
532362306a36Sopenharmony_ci				"\t\tBlock %3d: Start %4d, Count %4d\n",
532462306a36Sopenharmony_ci				index, rsrc_blks->rsrc_start,
532562306a36Sopenharmony_ci				rsrc_blks->rsrc_size);
532662306a36Sopenharmony_ci		index++;
532762306a36Sopenharmony_ci	}
532862306a36Sopenharmony_ci
532962306a36Sopenharmony_ci	len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
533062306a36Sopenharmony_ci			"\tXRI extents:\n");
533162306a36Sopenharmony_ci	index = 0;
533262306a36Sopenharmony_ci	list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_xri_blk_list,
533362306a36Sopenharmony_ci			    list) {
533462306a36Sopenharmony_ci		len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
533562306a36Sopenharmony_ci				"\t\tBlock %3d: Start %4d, Count %4d\n",
533662306a36Sopenharmony_ci				index, rsrc_blks->rsrc_start,
533762306a36Sopenharmony_ci				rsrc_blks->rsrc_size);
533862306a36Sopenharmony_ci		index++;
533962306a36Sopenharmony_ci	}
534062306a36Sopenharmony_ci
534162306a36Sopenharmony_ci	return len;
534262306a36Sopenharmony_ci}
534362306a36Sopenharmony_ci
534462306a36Sopenharmony_ci/**
534562306a36Sopenharmony_ci * lpfc_idiag_extacc_write - Syntax check and set up idiag extacc commands
534662306a36Sopenharmony_ci * @file: The file pointer to read from.
534762306a36Sopenharmony_ci * @buf: The buffer to copy the user data from.
534862306a36Sopenharmony_ci * @nbytes: The number of bytes to get.
534962306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
535062306a36Sopenharmony_ci *
535162306a36Sopenharmony_ci * This routine get the debugfs idiag command struct from user space and then
535262306a36Sopenharmony_ci * perform the syntax check for extent information access commands and sets
535362306a36Sopenharmony_ci * up the necessary states in the idiag command struct accordingly.
535462306a36Sopenharmony_ci *
535562306a36Sopenharmony_ci * It returns the @nbytges passing in from debugfs user space when successful.
535662306a36Sopenharmony_ci * In case of error conditions, it returns proper error code back to the user
535762306a36Sopenharmony_ci * space.
535862306a36Sopenharmony_ci **/
535962306a36Sopenharmony_cistatic ssize_t
536062306a36Sopenharmony_cilpfc_idiag_extacc_write(struct file *file, const char __user *buf,
536162306a36Sopenharmony_ci			size_t nbytes, loff_t *ppos)
536262306a36Sopenharmony_ci{
536362306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
536462306a36Sopenharmony_ci	uint32_t ext_map;
536562306a36Sopenharmony_ci	int rc;
536662306a36Sopenharmony_ci
536762306a36Sopenharmony_ci	/* This is a user write operation */
536862306a36Sopenharmony_ci	debug->op = LPFC_IDIAG_OP_WR;
536962306a36Sopenharmony_ci
537062306a36Sopenharmony_ci	rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
537162306a36Sopenharmony_ci	if (rc < 0)
537262306a36Sopenharmony_ci		return rc;
537362306a36Sopenharmony_ci
537462306a36Sopenharmony_ci	ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX];
537562306a36Sopenharmony_ci
537662306a36Sopenharmony_ci	if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD)
537762306a36Sopenharmony_ci		goto error_out;
537862306a36Sopenharmony_ci	if (rc != LPFC_EXT_ACC_CMD_ARG)
537962306a36Sopenharmony_ci		goto error_out;
538062306a36Sopenharmony_ci	if (!(ext_map & LPFC_EXT_ACC_ALL))
538162306a36Sopenharmony_ci		goto error_out;
538262306a36Sopenharmony_ci
538362306a36Sopenharmony_ci	return nbytes;
538462306a36Sopenharmony_cierror_out:
538562306a36Sopenharmony_ci	/* Clean out command structure on command error out */
538662306a36Sopenharmony_ci	memset(&idiag, 0, sizeof(idiag));
538762306a36Sopenharmony_ci	return -EINVAL;
538862306a36Sopenharmony_ci}
538962306a36Sopenharmony_ci
539062306a36Sopenharmony_ci/**
539162306a36Sopenharmony_ci * lpfc_idiag_extacc_read - idiag debugfs read access to extent information
539262306a36Sopenharmony_ci * @file: The file pointer to read from.
539362306a36Sopenharmony_ci * @buf: The buffer to copy the data to.
539462306a36Sopenharmony_ci * @nbytes: The number of bytes to read.
539562306a36Sopenharmony_ci * @ppos: The position in the file to start reading from.
539662306a36Sopenharmony_ci *
539762306a36Sopenharmony_ci * Description:
539862306a36Sopenharmony_ci * This routine reads data from the proper extent information according to
539962306a36Sopenharmony_ci * the idiag command, and copies to user @buf.
540062306a36Sopenharmony_ci *
540162306a36Sopenharmony_ci * Returns:
540262306a36Sopenharmony_ci * This function returns the amount of data that was read (this could be less
540362306a36Sopenharmony_ci * than @nbytes if the end of the file was reached) or a negative error value.
540462306a36Sopenharmony_ci **/
540562306a36Sopenharmony_cistatic ssize_t
540662306a36Sopenharmony_cilpfc_idiag_extacc_read(struct file *file, char __user *buf, size_t nbytes,
540762306a36Sopenharmony_ci		       loff_t *ppos)
540862306a36Sopenharmony_ci{
540962306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
541062306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
541162306a36Sopenharmony_ci	char *pbuffer;
541262306a36Sopenharmony_ci	uint32_t ext_map;
541362306a36Sopenharmony_ci	int len = 0;
541462306a36Sopenharmony_ci
541562306a36Sopenharmony_ci	/* This is a user read operation */
541662306a36Sopenharmony_ci	debug->op = LPFC_IDIAG_OP_RD;
541762306a36Sopenharmony_ci
541862306a36Sopenharmony_ci	if (!debug->buffer)
541962306a36Sopenharmony_ci		debug->buffer = kmalloc(LPFC_EXT_ACC_BUF_SIZE, GFP_KERNEL);
542062306a36Sopenharmony_ci	if (!debug->buffer)
542162306a36Sopenharmony_ci		return 0;
542262306a36Sopenharmony_ci	pbuffer = debug->buffer;
542362306a36Sopenharmony_ci	if (*ppos)
542462306a36Sopenharmony_ci		return 0;
542562306a36Sopenharmony_ci	if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD)
542662306a36Sopenharmony_ci		return 0;
542762306a36Sopenharmony_ci
542862306a36Sopenharmony_ci	ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX];
542962306a36Sopenharmony_ci	if (ext_map & LPFC_EXT_ACC_AVAIL)
543062306a36Sopenharmony_ci		len = lpfc_idiag_extacc_avail_get(phba, pbuffer, len);
543162306a36Sopenharmony_ci	if (ext_map & LPFC_EXT_ACC_ALLOC)
543262306a36Sopenharmony_ci		len = lpfc_idiag_extacc_alloc_get(phba, pbuffer, len);
543362306a36Sopenharmony_ci	if (ext_map & LPFC_EXT_ACC_DRIVR)
543462306a36Sopenharmony_ci		len = lpfc_idiag_extacc_drivr_get(phba, pbuffer, len);
543562306a36Sopenharmony_ci
543662306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
543762306a36Sopenharmony_ci}
543862306a36Sopenharmony_ci
543962306a36Sopenharmony_cistatic int
544062306a36Sopenharmony_cilpfc_cgn_buffer_open(struct inode *inode, struct file *file)
544162306a36Sopenharmony_ci{
544262306a36Sopenharmony_ci	struct lpfc_debug *debug;
544362306a36Sopenharmony_ci	int rc = -ENOMEM;
544462306a36Sopenharmony_ci
544562306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
544662306a36Sopenharmony_ci	if (!debug)
544762306a36Sopenharmony_ci		goto out;
544862306a36Sopenharmony_ci
544962306a36Sopenharmony_ci	debug->buffer = vmalloc(LPFC_CGN_BUF_SIZE);
545062306a36Sopenharmony_ci	if (!debug->buffer) {
545162306a36Sopenharmony_ci		kfree(debug);
545262306a36Sopenharmony_ci		goto out;
545362306a36Sopenharmony_ci	}
545462306a36Sopenharmony_ci
545562306a36Sopenharmony_ci	debug->i_private = inode->i_private;
545662306a36Sopenharmony_ci	file->private_data = debug;
545762306a36Sopenharmony_ci
545862306a36Sopenharmony_ci	rc = 0;
545962306a36Sopenharmony_ciout:
546062306a36Sopenharmony_ci	return rc;
546162306a36Sopenharmony_ci}
546262306a36Sopenharmony_ci
546362306a36Sopenharmony_cistatic ssize_t
546462306a36Sopenharmony_cilpfc_cgn_buffer_read(struct file *file, char __user *buf, size_t nbytes,
546562306a36Sopenharmony_ci		     loff_t *ppos)
546662306a36Sopenharmony_ci{
546762306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
546862306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
546962306a36Sopenharmony_ci	char *buffer = debug->buffer;
547062306a36Sopenharmony_ci	uint32_t *ptr;
547162306a36Sopenharmony_ci	int cnt, len = 0;
547262306a36Sopenharmony_ci
547362306a36Sopenharmony_ci	if (!phba->sli4_hba.pc_sli4_params.mi_ver || !phba->cgn_i) {
547462306a36Sopenharmony_ci		len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
547562306a36Sopenharmony_ci				 "Congestion Mgmt is not supported\n");
547662306a36Sopenharmony_ci		goto out;
547762306a36Sopenharmony_ci	}
547862306a36Sopenharmony_ci	ptr = (uint32_t *)phba->cgn_i->virt;
547962306a36Sopenharmony_ci	len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
548062306a36Sopenharmony_ci			 "Congestion Buffer Header\n");
548162306a36Sopenharmony_ci	/* Dump the first 32 bytes */
548262306a36Sopenharmony_ci	cnt = 32;
548362306a36Sopenharmony_ci	len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
548462306a36Sopenharmony_ci			 "000: %08x %08x %08x %08x %08x %08x %08x %08x\n",
548562306a36Sopenharmony_ci			 *ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3),
548662306a36Sopenharmony_ci			 *(ptr + 4), *(ptr + 5), *(ptr + 6), *(ptr + 7));
548762306a36Sopenharmony_ci	ptr += 8;
548862306a36Sopenharmony_ci	len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
548962306a36Sopenharmony_ci			 "Congestion Buffer Data\n");
549062306a36Sopenharmony_ci	while (cnt < sizeof(struct lpfc_cgn_info)) {
549162306a36Sopenharmony_ci		if (len > (LPFC_CGN_BUF_SIZE - LPFC_DEBUG_OUT_LINE_SZ)) {
549262306a36Sopenharmony_ci			len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
549362306a36Sopenharmony_ci					 "Truncated . . .\n");
549462306a36Sopenharmony_ci			goto out;
549562306a36Sopenharmony_ci		}
549662306a36Sopenharmony_ci		len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
549762306a36Sopenharmony_ci				 "%03x: %08x %08x %08x %08x "
549862306a36Sopenharmony_ci				 "%08x %08x %08x %08x\n",
549962306a36Sopenharmony_ci				 cnt, *ptr, *(ptr + 1), *(ptr + 2),
550062306a36Sopenharmony_ci				 *(ptr + 3), *(ptr + 4), *(ptr + 5),
550162306a36Sopenharmony_ci				 *(ptr + 6), *(ptr + 7));
550262306a36Sopenharmony_ci		cnt += 32;
550362306a36Sopenharmony_ci		ptr += 8;
550462306a36Sopenharmony_ci	}
550562306a36Sopenharmony_ci	if (len > (LPFC_CGN_BUF_SIZE - LPFC_DEBUG_OUT_LINE_SZ)) {
550662306a36Sopenharmony_ci		len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
550762306a36Sopenharmony_ci				 "Truncated . . .\n");
550862306a36Sopenharmony_ci		goto out;
550962306a36Sopenharmony_ci	}
551062306a36Sopenharmony_ci	len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
551162306a36Sopenharmony_ci			 "Parameter Data\n");
551262306a36Sopenharmony_ci	ptr = (uint32_t *)&phba->cgn_p;
551362306a36Sopenharmony_ci	len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
551462306a36Sopenharmony_ci			 "%08x %08x %08x %08x\n",
551562306a36Sopenharmony_ci			 *ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3));
551662306a36Sopenharmony_ciout:
551762306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, buffer, len);
551862306a36Sopenharmony_ci}
551962306a36Sopenharmony_ci
552062306a36Sopenharmony_cistatic int
552162306a36Sopenharmony_cilpfc_cgn_buffer_release(struct inode *inode, struct file *file)
552262306a36Sopenharmony_ci{
552362306a36Sopenharmony_ci	struct lpfc_debug *debug = file->private_data;
552462306a36Sopenharmony_ci
552562306a36Sopenharmony_ci	vfree(debug->buffer);
552662306a36Sopenharmony_ci	kfree(debug);
552762306a36Sopenharmony_ci
552862306a36Sopenharmony_ci	return 0;
552962306a36Sopenharmony_ci}
553062306a36Sopenharmony_ci
553162306a36Sopenharmony_cistatic int
553262306a36Sopenharmony_cilpfc_rx_monitor_open(struct inode *inode, struct file *file)
553362306a36Sopenharmony_ci{
553462306a36Sopenharmony_ci	struct lpfc_rx_monitor_debug *debug;
553562306a36Sopenharmony_ci	int rc = -ENOMEM;
553662306a36Sopenharmony_ci
553762306a36Sopenharmony_ci	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
553862306a36Sopenharmony_ci	if (!debug)
553962306a36Sopenharmony_ci		goto out;
554062306a36Sopenharmony_ci
554162306a36Sopenharmony_ci	debug->buffer = vmalloc(MAX_DEBUGFS_RX_INFO_SIZE);
554262306a36Sopenharmony_ci	if (!debug->buffer) {
554362306a36Sopenharmony_ci		kfree(debug);
554462306a36Sopenharmony_ci		goto out;
554562306a36Sopenharmony_ci	}
554662306a36Sopenharmony_ci
554762306a36Sopenharmony_ci	debug->i_private = inode->i_private;
554862306a36Sopenharmony_ci	file->private_data = debug;
554962306a36Sopenharmony_ci
555062306a36Sopenharmony_ci	rc = 0;
555162306a36Sopenharmony_ciout:
555262306a36Sopenharmony_ci	return rc;
555362306a36Sopenharmony_ci}
555462306a36Sopenharmony_ci
555562306a36Sopenharmony_cistatic ssize_t
555662306a36Sopenharmony_cilpfc_rx_monitor_read(struct file *file, char __user *buf, size_t nbytes,
555762306a36Sopenharmony_ci		     loff_t *ppos)
555862306a36Sopenharmony_ci{
555962306a36Sopenharmony_ci	struct lpfc_rx_monitor_debug *debug = file->private_data;
556062306a36Sopenharmony_ci	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
556162306a36Sopenharmony_ci	char *buffer = debug->buffer;
556262306a36Sopenharmony_ci
556362306a36Sopenharmony_ci	if (!phba->rx_monitor) {
556462306a36Sopenharmony_ci		scnprintf(buffer, MAX_DEBUGFS_RX_INFO_SIZE,
556562306a36Sopenharmony_ci			  "Rx Monitor Info is empty.\n");
556662306a36Sopenharmony_ci	} else {
556762306a36Sopenharmony_ci		lpfc_rx_monitor_report(phba, phba->rx_monitor, buffer,
556862306a36Sopenharmony_ci				       MAX_DEBUGFS_RX_INFO_SIZE,
556962306a36Sopenharmony_ci				       LPFC_MAX_RXMONITOR_ENTRY);
557062306a36Sopenharmony_ci	}
557162306a36Sopenharmony_ci
557262306a36Sopenharmony_ci	return simple_read_from_buffer(buf, nbytes, ppos, buffer,
557362306a36Sopenharmony_ci				       strlen(buffer));
557462306a36Sopenharmony_ci}
557562306a36Sopenharmony_ci
557662306a36Sopenharmony_cistatic int
557762306a36Sopenharmony_cilpfc_rx_monitor_release(struct inode *inode, struct file *file)
557862306a36Sopenharmony_ci{
557962306a36Sopenharmony_ci	struct lpfc_rx_monitor_debug *debug = file->private_data;
558062306a36Sopenharmony_ci
558162306a36Sopenharmony_ci	vfree(debug->buffer);
558262306a36Sopenharmony_ci	kfree(debug);
558362306a36Sopenharmony_ci
558462306a36Sopenharmony_ci	return 0;
558562306a36Sopenharmony_ci}
558662306a36Sopenharmony_ci
558762306a36Sopenharmony_ci#undef lpfc_debugfs_op_disc_trc
558862306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_disc_trc = {
558962306a36Sopenharmony_ci	.owner =        THIS_MODULE,
559062306a36Sopenharmony_ci	.open =         lpfc_debugfs_disc_trc_open,
559162306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
559262306a36Sopenharmony_ci	.read =         lpfc_debugfs_read,
559362306a36Sopenharmony_ci	.release =      lpfc_debugfs_release,
559462306a36Sopenharmony_ci};
559562306a36Sopenharmony_ci
559662306a36Sopenharmony_ci#undef lpfc_debugfs_op_nodelist
559762306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_nodelist = {
559862306a36Sopenharmony_ci	.owner =        THIS_MODULE,
559962306a36Sopenharmony_ci	.open =         lpfc_debugfs_nodelist_open,
560062306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
560162306a36Sopenharmony_ci	.read =         lpfc_debugfs_read,
560262306a36Sopenharmony_ci	.release =      lpfc_debugfs_release,
560362306a36Sopenharmony_ci};
560462306a36Sopenharmony_ci
560562306a36Sopenharmony_ci#undef lpfc_debugfs_op_multixripools
560662306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_multixripools = {
560762306a36Sopenharmony_ci	.owner =        THIS_MODULE,
560862306a36Sopenharmony_ci	.open =         lpfc_debugfs_multixripools_open,
560962306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
561062306a36Sopenharmony_ci	.read =         lpfc_debugfs_read,
561162306a36Sopenharmony_ci	.write =	lpfc_debugfs_multixripools_write,
561262306a36Sopenharmony_ci	.release =      lpfc_debugfs_release,
561362306a36Sopenharmony_ci};
561462306a36Sopenharmony_ci
561562306a36Sopenharmony_ci#undef lpfc_debugfs_op_hbqinfo
561662306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_hbqinfo = {
561762306a36Sopenharmony_ci	.owner =        THIS_MODULE,
561862306a36Sopenharmony_ci	.open =         lpfc_debugfs_hbqinfo_open,
561962306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
562062306a36Sopenharmony_ci	.read =         lpfc_debugfs_read,
562162306a36Sopenharmony_ci	.release =      lpfc_debugfs_release,
562262306a36Sopenharmony_ci};
562362306a36Sopenharmony_ci
562462306a36Sopenharmony_ci#ifdef LPFC_HDWQ_LOCK_STAT
562562306a36Sopenharmony_ci#undef lpfc_debugfs_op_lockstat
562662306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_lockstat = {
562762306a36Sopenharmony_ci	.owner =        THIS_MODULE,
562862306a36Sopenharmony_ci	.open =         lpfc_debugfs_lockstat_open,
562962306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
563062306a36Sopenharmony_ci	.read =         lpfc_debugfs_read,
563162306a36Sopenharmony_ci	.write =        lpfc_debugfs_lockstat_write,
563262306a36Sopenharmony_ci	.release =      lpfc_debugfs_release,
563362306a36Sopenharmony_ci};
563462306a36Sopenharmony_ci#endif
563562306a36Sopenharmony_ci
563662306a36Sopenharmony_ci#undef lpfc_debugfs_ras_log
563762306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_ras_log = {
563862306a36Sopenharmony_ci	.owner =        THIS_MODULE,
563962306a36Sopenharmony_ci	.open =         lpfc_debugfs_ras_log_open,
564062306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
564162306a36Sopenharmony_ci	.read =         lpfc_debugfs_read,
564262306a36Sopenharmony_ci	.release =      lpfc_debugfs_ras_log_release,
564362306a36Sopenharmony_ci};
564462306a36Sopenharmony_ci
564562306a36Sopenharmony_ci#undef lpfc_debugfs_op_dumpHBASlim
564662306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_dumpHBASlim = {
564762306a36Sopenharmony_ci	.owner =        THIS_MODULE,
564862306a36Sopenharmony_ci	.open =         lpfc_debugfs_dumpHBASlim_open,
564962306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
565062306a36Sopenharmony_ci	.read =         lpfc_debugfs_read,
565162306a36Sopenharmony_ci	.release =      lpfc_debugfs_release,
565262306a36Sopenharmony_ci};
565362306a36Sopenharmony_ci
565462306a36Sopenharmony_ci#undef lpfc_debugfs_op_dumpHostSlim
565562306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_dumpHostSlim = {
565662306a36Sopenharmony_ci	.owner =        THIS_MODULE,
565762306a36Sopenharmony_ci	.open =         lpfc_debugfs_dumpHostSlim_open,
565862306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
565962306a36Sopenharmony_ci	.read =         lpfc_debugfs_read,
566062306a36Sopenharmony_ci	.release =      lpfc_debugfs_release,
566162306a36Sopenharmony_ci};
566262306a36Sopenharmony_ci
566362306a36Sopenharmony_ci#undef lpfc_debugfs_op_nvmestat
566462306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_nvmestat = {
566562306a36Sopenharmony_ci	.owner =        THIS_MODULE,
566662306a36Sopenharmony_ci	.open =         lpfc_debugfs_nvmestat_open,
566762306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
566862306a36Sopenharmony_ci	.read =         lpfc_debugfs_read,
566962306a36Sopenharmony_ci	.write =	lpfc_debugfs_nvmestat_write,
567062306a36Sopenharmony_ci	.release =      lpfc_debugfs_release,
567162306a36Sopenharmony_ci};
567262306a36Sopenharmony_ci
567362306a36Sopenharmony_ci#undef lpfc_debugfs_op_scsistat
567462306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_scsistat = {
567562306a36Sopenharmony_ci	.owner =        THIS_MODULE,
567662306a36Sopenharmony_ci	.open =         lpfc_debugfs_scsistat_open,
567762306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
567862306a36Sopenharmony_ci	.read =         lpfc_debugfs_read,
567962306a36Sopenharmony_ci	.write =	lpfc_debugfs_scsistat_write,
568062306a36Sopenharmony_ci	.release =      lpfc_debugfs_release,
568162306a36Sopenharmony_ci};
568262306a36Sopenharmony_ci
568362306a36Sopenharmony_ci#undef lpfc_debugfs_op_ioktime
568462306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_ioktime = {
568562306a36Sopenharmony_ci	.owner =        THIS_MODULE,
568662306a36Sopenharmony_ci	.open =         lpfc_debugfs_ioktime_open,
568762306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
568862306a36Sopenharmony_ci	.read =         lpfc_debugfs_read,
568962306a36Sopenharmony_ci	.write =	lpfc_debugfs_ioktime_write,
569062306a36Sopenharmony_ci	.release =      lpfc_debugfs_release,
569162306a36Sopenharmony_ci};
569262306a36Sopenharmony_ci
569362306a36Sopenharmony_ci#undef lpfc_debugfs_op_nvmeio_trc
569462306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_nvmeio_trc = {
569562306a36Sopenharmony_ci	.owner =        THIS_MODULE,
569662306a36Sopenharmony_ci	.open =         lpfc_debugfs_nvmeio_trc_open,
569762306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
569862306a36Sopenharmony_ci	.read =         lpfc_debugfs_read,
569962306a36Sopenharmony_ci	.write =	lpfc_debugfs_nvmeio_trc_write,
570062306a36Sopenharmony_ci	.release =      lpfc_debugfs_release,
570162306a36Sopenharmony_ci};
570262306a36Sopenharmony_ci
570362306a36Sopenharmony_ci#undef lpfc_debugfs_op_hdwqstat
570462306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_hdwqstat = {
570562306a36Sopenharmony_ci	.owner =        THIS_MODULE,
570662306a36Sopenharmony_ci	.open =         lpfc_debugfs_hdwqstat_open,
570762306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
570862306a36Sopenharmony_ci	.read =         lpfc_debugfs_read,
570962306a36Sopenharmony_ci	.write =	lpfc_debugfs_hdwqstat_write,
571062306a36Sopenharmony_ci	.release =      lpfc_debugfs_release,
571162306a36Sopenharmony_ci};
571262306a36Sopenharmony_ci
571362306a36Sopenharmony_ci#undef lpfc_debugfs_op_dif_err
571462306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_dif_err = {
571562306a36Sopenharmony_ci	.owner =	THIS_MODULE,
571662306a36Sopenharmony_ci	.open =		simple_open,
571762306a36Sopenharmony_ci	.llseek =	lpfc_debugfs_lseek,
571862306a36Sopenharmony_ci	.read =		lpfc_debugfs_dif_err_read,
571962306a36Sopenharmony_ci	.write =	lpfc_debugfs_dif_err_write,
572062306a36Sopenharmony_ci	.release =	lpfc_debugfs_dif_err_release,
572162306a36Sopenharmony_ci};
572262306a36Sopenharmony_ci
572362306a36Sopenharmony_ci#undef lpfc_debugfs_op_slow_ring_trc
572462306a36Sopenharmony_cistatic const struct file_operations lpfc_debugfs_op_slow_ring_trc = {
572562306a36Sopenharmony_ci	.owner =        THIS_MODULE,
572662306a36Sopenharmony_ci	.open =         lpfc_debugfs_slow_ring_trc_open,
572762306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
572862306a36Sopenharmony_ci	.read =         lpfc_debugfs_read,
572962306a36Sopenharmony_ci	.release =      lpfc_debugfs_release,
573062306a36Sopenharmony_ci};
573162306a36Sopenharmony_ci
573262306a36Sopenharmony_cistatic struct dentry *lpfc_debugfs_root = NULL;
573362306a36Sopenharmony_cistatic atomic_t lpfc_debugfs_hba_count;
573462306a36Sopenharmony_ci
573562306a36Sopenharmony_ci/*
573662306a36Sopenharmony_ci * File operations for the iDiag debugfs
573762306a36Sopenharmony_ci */
573862306a36Sopenharmony_ci#undef lpfc_idiag_op_pciCfg
573962306a36Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_pciCfg = {
574062306a36Sopenharmony_ci	.owner =        THIS_MODULE,
574162306a36Sopenharmony_ci	.open =         lpfc_idiag_open,
574262306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
574362306a36Sopenharmony_ci	.read =         lpfc_idiag_pcicfg_read,
574462306a36Sopenharmony_ci	.write =        lpfc_idiag_pcicfg_write,
574562306a36Sopenharmony_ci	.release =      lpfc_idiag_cmd_release,
574662306a36Sopenharmony_ci};
574762306a36Sopenharmony_ci
574862306a36Sopenharmony_ci#undef lpfc_idiag_op_barAcc
574962306a36Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_barAcc = {
575062306a36Sopenharmony_ci	.owner =        THIS_MODULE,
575162306a36Sopenharmony_ci	.open =         lpfc_idiag_open,
575262306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
575362306a36Sopenharmony_ci	.read =         lpfc_idiag_baracc_read,
575462306a36Sopenharmony_ci	.write =        lpfc_idiag_baracc_write,
575562306a36Sopenharmony_ci	.release =      lpfc_idiag_cmd_release,
575662306a36Sopenharmony_ci};
575762306a36Sopenharmony_ci
575862306a36Sopenharmony_ci#undef lpfc_idiag_op_queInfo
575962306a36Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_queInfo = {
576062306a36Sopenharmony_ci	.owner =        THIS_MODULE,
576162306a36Sopenharmony_ci	.open =         lpfc_idiag_open,
576262306a36Sopenharmony_ci	.read =         lpfc_idiag_queinfo_read,
576362306a36Sopenharmony_ci	.release =      lpfc_idiag_release,
576462306a36Sopenharmony_ci};
576562306a36Sopenharmony_ci
576662306a36Sopenharmony_ci#undef lpfc_idiag_op_queAcc
576762306a36Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_queAcc = {
576862306a36Sopenharmony_ci	.owner =        THIS_MODULE,
576962306a36Sopenharmony_ci	.open =         lpfc_idiag_open,
577062306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
577162306a36Sopenharmony_ci	.read =         lpfc_idiag_queacc_read,
577262306a36Sopenharmony_ci	.write =        lpfc_idiag_queacc_write,
577362306a36Sopenharmony_ci	.release =      lpfc_idiag_cmd_release,
577462306a36Sopenharmony_ci};
577562306a36Sopenharmony_ci
577662306a36Sopenharmony_ci#undef lpfc_idiag_op_drbAcc
577762306a36Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_drbAcc = {
577862306a36Sopenharmony_ci	.owner =        THIS_MODULE,
577962306a36Sopenharmony_ci	.open =         lpfc_idiag_open,
578062306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
578162306a36Sopenharmony_ci	.read =         lpfc_idiag_drbacc_read,
578262306a36Sopenharmony_ci	.write =        lpfc_idiag_drbacc_write,
578362306a36Sopenharmony_ci	.release =      lpfc_idiag_cmd_release,
578462306a36Sopenharmony_ci};
578562306a36Sopenharmony_ci
578662306a36Sopenharmony_ci#undef lpfc_idiag_op_ctlAcc
578762306a36Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_ctlAcc = {
578862306a36Sopenharmony_ci	.owner =        THIS_MODULE,
578962306a36Sopenharmony_ci	.open =         lpfc_idiag_open,
579062306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
579162306a36Sopenharmony_ci	.read =         lpfc_idiag_ctlacc_read,
579262306a36Sopenharmony_ci	.write =        lpfc_idiag_ctlacc_write,
579362306a36Sopenharmony_ci	.release =      lpfc_idiag_cmd_release,
579462306a36Sopenharmony_ci};
579562306a36Sopenharmony_ci
579662306a36Sopenharmony_ci#undef lpfc_idiag_op_mbxAcc
579762306a36Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_mbxAcc = {
579862306a36Sopenharmony_ci	.owner =        THIS_MODULE,
579962306a36Sopenharmony_ci	.open =         lpfc_idiag_open,
580062306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
580162306a36Sopenharmony_ci	.read =         lpfc_idiag_mbxacc_read,
580262306a36Sopenharmony_ci	.write =        lpfc_idiag_mbxacc_write,
580362306a36Sopenharmony_ci	.release =      lpfc_idiag_cmd_release,
580462306a36Sopenharmony_ci};
580562306a36Sopenharmony_ci
580662306a36Sopenharmony_ci#undef lpfc_idiag_op_extAcc
580762306a36Sopenharmony_cistatic const struct file_operations lpfc_idiag_op_extAcc = {
580862306a36Sopenharmony_ci	.owner =        THIS_MODULE,
580962306a36Sopenharmony_ci	.open =         lpfc_idiag_open,
581062306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
581162306a36Sopenharmony_ci	.read =         lpfc_idiag_extacc_read,
581262306a36Sopenharmony_ci	.write =        lpfc_idiag_extacc_write,
581362306a36Sopenharmony_ci	.release =      lpfc_idiag_cmd_release,
581462306a36Sopenharmony_ci};
581562306a36Sopenharmony_ci#undef lpfc_cgn_buffer_op
581662306a36Sopenharmony_cistatic const struct file_operations lpfc_cgn_buffer_op = {
581762306a36Sopenharmony_ci	.owner =        THIS_MODULE,
581862306a36Sopenharmony_ci	.open =         lpfc_cgn_buffer_open,
581962306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
582062306a36Sopenharmony_ci	.read =         lpfc_cgn_buffer_read,
582162306a36Sopenharmony_ci	.release =      lpfc_cgn_buffer_release,
582262306a36Sopenharmony_ci};
582362306a36Sopenharmony_ci
582462306a36Sopenharmony_ci#undef lpfc_rx_monitor_op
582562306a36Sopenharmony_cistatic const struct file_operations lpfc_rx_monitor_op = {
582662306a36Sopenharmony_ci	.owner =        THIS_MODULE,
582762306a36Sopenharmony_ci	.open =         lpfc_rx_monitor_open,
582862306a36Sopenharmony_ci	.llseek =       lpfc_debugfs_lseek,
582962306a36Sopenharmony_ci	.read =         lpfc_rx_monitor_read,
583062306a36Sopenharmony_ci	.release =      lpfc_rx_monitor_release,
583162306a36Sopenharmony_ci};
583262306a36Sopenharmony_ci#endif
583362306a36Sopenharmony_ci
583462306a36Sopenharmony_ci/* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command
583562306a36Sopenharmony_ci * @phba: Pointer to HBA context object.
583662306a36Sopenharmony_ci * @dmabuf: Pointer to a DMA buffer descriptor.
583762306a36Sopenharmony_ci *
583862306a36Sopenharmony_ci * Description:
583962306a36Sopenharmony_ci * This routine dump a bsg pass-through non-embedded mailbox command with
584062306a36Sopenharmony_ci * external buffer.
584162306a36Sopenharmony_ci **/
584262306a36Sopenharmony_civoid
584362306a36Sopenharmony_cilpfc_idiag_mbxacc_dump_bsg_mbox(struct lpfc_hba *phba, enum nemb_type nemb_tp,
584462306a36Sopenharmony_ci				enum mbox_type mbox_tp, enum dma_type dma_tp,
584562306a36Sopenharmony_ci				enum sta_type sta_tp,
584662306a36Sopenharmony_ci				struct lpfc_dmabuf *dmabuf, uint32_t ext_buf)
584762306a36Sopenharmony_ci{
584862306a36Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
584962306a36Sopenharmony_ci	uint32_t *mbx_mbox_cmd, *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt;
585062306a36Sopenharmony_ci	char line_buf[LPFC_MBX_ACC_LBUF_SZ];
585162306a36Sopenharmony_ci	int len = 0;
585262306a36Sopenharmony_ci	uint32_t do_dump = 0;
585362306a36Sopenharmony_ci	uint32_t *pword;
585462306a36Sopenharmony_ci	uint32_t i;
585562306a36Sopenharmony_ci
585662306a36Sopenharmony_ci	if (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP)
585762306a36Sopenharmony_ci		return;
585862306a36Sopenharmony_ci
585962306a36Sopenharmony_ci	mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
586062306a36Sopenharmony_ci	mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
586162306a36Sopenharmony_ci	mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
586262306a36Sopenharmony_ci	mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
586362306a36Sopenharmony_ci
586462306a36Sopenharmony_ci	if (!(*mbx_dump_map & LPFC_MBX_DMP_ALL) ||
586562306a36Sopenharmony_ci	    (*mbx_dump_cnt == 0) ||
586662306a36Sopenharmony_ci	    (*mbx_word_cnt == 0))
586762306a36Sopenharmony_ci		return;
586862306a36Sopenharmony_ci
586962306a36Sopenharmony_ci	if (*mbx_mbox_cmd != 0x9B)
587062306a36Sopenharmony_ci		return;
587162306a36Sopenharmony_ci
587262306a36Sopenharmony_ci	if ((mbox_tp == mbox_rd) && (dma_tp == dma_mbox)) {
587362306a36Sopenharmony_ci		if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_MBX) {
587462306a36Sopenharmony_ci			do_dump |= LPFC_BSG_DMP_MBX_RD_MBX;
587562306a36Sopenharmony_ci			pr_err("\nRead mbox command (x%x), "
587662306a36Sopenharmony_ci			       "nemb:0x%x, extbuf_cnt:%d:\n",
587762306a36Sopenharmony_ci			       sta_tp, nemb_tp, ext_buf);
587862306a36Sopenharmony_ci		}
587962306a36Sopenharmony_ci	}
588062306a36Sopenharmony_ci	if ((mbox_tp == mbox_rd) && (dma_tp == dma_ebuf)) {
588162306a36Sopenharmony_ci		if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_BUF) {
588262306a36Sopenharmony_ci			do_dump |= LPFC_BSG_DMP_MBX_RD_BUF;
588362306a36Sopenharmony_ci			pr_err("\nRead mbox buffer (x%x), "
588462306a36Sopenharmony_ci			       "nemb:0x%x, extbuf_seq:%d:\n",
588562306a36Sopenharmony_ci			       sta_tp, nemb_tp, ext_buf);
588662306a36Sopenharmony_ci		}
588762306a36Sopenharmony_ci	}
588862306a36Sopenharmony_ci	if ((mbox_tp == mbox_wr) && (dma_tp == dma_mbox)) {
588962306a36Sopenharmony_ci		if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_MBX) {
589062306a36Sopenharmony_ci			do_dump |= LPFC_BSG_DMP_MBX_WR_MBX;
589162306a36Sopenharmony_ci			pr_err("\nWrite mbox command (x%x), "
589262306a36Sopenharmony_ci			       "nemb:0x%x, extbuf_cnt:%d:\n",
589362306a36Sopenharmony_ci			       sta_tp, nemb_tp, ext_buf);
589462306a36Sopenharmony_ci		}
589562306a36Sopenharmony_ci	}
589662306a36Sopenharmony_ci	if ((mbox_tp == mbox_wr) && (dma_tp == dma_ebuf)) {
589762306a36Sopenharmony_ci		if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_BUF) {
589862306a36Sopenharmony_ci			do_dump |= LPFC_BSG_DMP_MBX_WR_BUF;
589962306a36Sopenharmony_ci			pr_err("\nWrite mbox buffer (x%x), "
590062306a36Sopenharmony_ci			       "nemb:0x%x, extbuf_seq:%d:\n",
590162306a36Sopenharmony_ci			       sta_tp, nemb_tp, ext_buf);
590262306a36Sopenharmony_ci		}
590362306a36Sopenharmony_ci	}
590462306a36Sopenharmony_ci
590562306a36Sopenharmony_ci	/* dump buffer content */
590662306a36Sopenharmony_ci	if (do_dump) {
590762306a36Sopenharmony_ci		pword = (uint32_t *)dmabuf->virt;
590862306a36Sopenharmony_ci		for (i = 0; i < *mbx_word_cnt; i++) {
590962306a36Sopenharmony_ci			if (!(i % 8)) {
591062306a36Sopenharmony_ci				if (i != 0)
591162306a36Sopenharmony_ci					pr_err("%s\n", line_buf);
591262306a36Sopenharmony_ci				len = 0;
591362306a36Sopenharmony_ci				len += scnprintf(line_buf+len,
591462306a36Sopenharmony_ci						LPFC_MBX_ACC_LBUF_SZ-len,
591562306a36Sopenharmony_ci						"%03d: ", i);
591662306a36Sopenharmony_ci			}
591762306a36Sopenharmony_ci			len += scnprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len,
591862306a36Sopenharmony_ci					"%08x ", (uint32_t)*pword);
591962306a36Sopenharmony_ci			pword++;
592062306a36Sopenharmony_ci		}
592162306a36Sopenharmony_ci		if ((i - 1) % 8)
592262306a36Sopenharmony_ci			pr_err("%s\n", line_buf);
592362306a36Sopenharmony_ci		(*mbx_dump_cnt)--;
592462306a36Sopenharmony_ci	}
592562306a36Sopenharmony_ci
592662306a36Sopenharmony_ci	/* Clean out command structure on reaching dump count */
592762306a36Sopenharmony_ci	if (*mbx_dump_cnt == 0)
592862306a36Sopenharmony_ci		memset(&idiag, 0, sizeof(idiag));
592962306a36Sopenharmony_ci	return;
593062306a36Sopenharmony_ci#endif
593162306a36Sopenharmony_ci}
593262306a36Sopenharmony_ci
593362306a36Sopenharmony_ci/* lpfc_idiag_mbxacc_dump_issue_mbox - idiag debugfs dump issue mailbox command
593462306a36Sopenharmony_ci * @phba: Pointer to HBA context object.
593562306a36Sopenharmony_ci * @dmabuf: Pointer to a DMA buffer descriptor.
593662306a36Sopenharmony_ci *
593762306a36Sopenharmony_ci * Description:
593862306a36Sopenharmony_ci * This routine dump a pass-through non-embedded mailbox command from issue
593962306a36Sopenharmony_ci * mailbox command.
594062306a36Sopenharmony_ci **/
594162306a36Sopenharmony_civoid
594262306a36Sopenharmony_cilpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *phba, MAILBOX_t *pmbox)
594362306a36Sopenharmony_ci{
594462306a36Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
594562306a36Sopenharmony_ci	uint32_t *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt, *mbx_mbox_cmd;
594662306a36Sopenharmony_ci	char line_buf[LPFC_MBX_ACC_LBUF_SZ];
594762306a36Sopenharmony_ci	int len = 0;
594862306a36Sopenharmony_ci	uint32_t *pword;
594962306a36Sopenharmony_ci	uint8_t *pbyte;
595062306a36Sopenharmony_ci	uint32_t i, j;
595162306a36Sopenharmony_ci
595262306a36Sopenharmony_ci	if (idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP)
595362306a36Sopenharmony_ci		return;
595462306a36Sopenharmony_ci
595562306a36Sopenharmony_ci	mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
595662306a36Sopenharmony_ci	mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
595762306a36Sopenharmony_ci	mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
595862306a36Sopenharmony_ci	mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
595962306a36Sopenharmony_ci
596062306a36Sopenharmony_ci	if (!(*mbx_dump_map & LPFC_MBX_DMP_MBX_ALL) ||
596162306a36Sopenharmony_ci	    (*mbx_dump_cnt == 0) ||
596262306a36Sopenharmony_ci	    (*mbx_word_cnt == 0))
596362306a36Sopenharmony_ci		return;
596462306a36Sopenharmony_ci
596562306a36Sopenharmony_ci	if ((*mbx_mbox_cmd != LPFC_MBX_ALL_CMD) &&
596662306a36Sopenharmony_ci	    (*mbx_mbox_cmd != pmbox->mbxCommand))
596762306a36Sopenharmony_ci		return;
596862306a36Sopenharmony_ci
596962306a36Sopenharmony_ci	/* dump buffer content */
597062306a36Sopenharmony_ci	if (*mbx_dump_map & LPFC_MBX_DMP_MBX_WORD) {
597162306a36Sopenharmony_ci		pr_err("Mailbox command:0x%x dump by word:\n",
597262306a36Sopenharmony_ci		       pmbox->mbxCommand);
597362306a36Sopenharmony_ci		pword = (uint32_t *)pmbox;
597462306a36Sopenharmony_ci		for (i = 0; i < *mbx_word_cnt; i++) {
597562306a36Sopenharmony_ci			if (!(i % 8)) {
597662306a36Sopenharmony_ci				if (i != 0)
597762306a36Sopenharmony_ci					pr_err("%s\n", line_buf);
597862306a36Sopenharmony_ci				len = 0;
597962306a36Sopenharmony_ci				memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ);
598062306a36Sopenharmony_ci				len += scnprintf(line_buf+len,
598162306a36Sopenharmony_ci						LPFC_MBX_ACC_LBUF_SZ-len,
598262306a36Sopenharmony_ci						"%03d: ", i);
598362306a36Sopenharmony_ci			}
598462306a36Sopenharmony_ci			len += scnprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len,
598562306a36Sopenharmony_ci					"%08x ",
598662306a36Sopenharmony_ci					((uint32_t)*pword) & 0xffffffff);
598762306a36Sopenharmony_ci			pword++;
598862306a36Sopenharmony_ci		}
598962306a36Sopenharmony_ci		if ((i - 1) % 8)
599062306a36Sopenharmony_ci			pr_err("%s\n", line_buf);
599162306a36Sopenharmony_ci		pr_err("\n");
599262306a36Sopenharmony_ci	}
599362306a36Sopenharmony_ci	if (*mbx_dump_map & LPFC_MBX_DMP_MBX_BYTE) {
599462306a36Sopenharmony_ci		pr_err("Mailbox command:0x%x dump by byte:\n",
599562306a36Sopenharmony_ci		       pmbox->mbxCommand);
599662306a36Sopenharmony_ci		pbyte = (uint8_t *)pmbox;
599762306a36Sopenharmony_ci		for (i = 0; i < *mbx_word_cnt; i++) {
599862306a36Sopenharmony_ci			if (!(i % 8)) {
599962306a36Sopenharmony_ci				if (i != 0)
600062306a36Sopenharmony_ci					pr_err("%s\n", line_buf);
600162306a36Sopenharmony_ci				len = 0;
600262306a36Sopenharmony_ci				memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ);
600362306a36Sopenharmony_ci				len += scnprintf(line_buf+len,
600462306a36Sopenharmony_ci						LPFC_MBX_ACC_LBUF_SZ-len,
600562306a36Sopenharmony_ci						"%03d: ", i);
600662306a36Sopenharmony_ci			}
600762306a36Sopenharmony_ci			for (j = 0; j < 4; j++) {
600862306a36Sopenharmony_ci				len += scnprintf(line_buf+len,
600962306a36Sopenharmony_ci						LPFC_MBX_ACC_LBUF_SZ-len,
601062306a36Sopenharmony_ci						"%02x",
601162306a36Sopenharmony_ci						((uint8_t)*pbyte) & 0xff);
601262306a36Sopenharmony_ci				pbyte++;
601362306a36Sopenharmony_ci			}
601462306a36Sopenharmony_ci			len += scnprintf(line_buf+len,
601562306a36Sopenharmony_ci					LPFC_MBX_ACC_LBUF_SZ-len, " ");
601662306a36Sopenharmony_ci		}
601762306a36Sopenharmony_ci		if ((i - 1) % 8)
601862306a36Sopenharmony_ci			pr_err("%s\n", line_buf);
601962306a36Sopenharmony_ci		pr_err("\n");
602062306a36Sopenharmony_ci	}
602162306a36Sopenharmony_ci	(*mbx_dump_cnt)--;
602262306a36Sopenharmony_ci
602362306a36Sopenharmony_ci	/* Clean out command structure on reaching dump count */
602462306a36Sopenharmony_ci	if (*mbx_dump_cnt == 0)
602562306a36Sopenharmony_ci		memset(&idiag, 0, sizeof(idiag));
602662306a36Sopenharmony_ci	return;
602762306a36Sopenharmony_ci#endif
602862306a36Sopenharmony_ci}
602962306a36Sopenharmony_ci
603062306a36Sopenharmony_ci/**
603162306a36Sopenharmony_ci * lpfc_debugfs_initialize - Initialize debugfs for a vport
603262306a36Sopenharmony_ci * @vport: The vport pointer to initialize.
603362306a36Sopenharmony_ci *
603462306a36Sopenharmony_ci * Description:
603562306a36Sopenharmony_ci * When Debugfs is configured this routine sets up the lpfc debugfs file system.
603662306a36Sopenharmony_ci * If not already created, this routine will create the lpfc directory, and
603762306a36Sopenharmony_ci * lpfcX directory (for this HBA), and vportX directory for this vport. It will
603862306a36Sopenharmony_ci * also create each file used to access lpfc specific debugfs information.
603962306a36Sopenharmony_ci **/
604062306a36Sopenharmony_ciinline void
604162306a36Sopenharmony_cilpfc_debugfs_initialize(struct lpfc_vport *vport)
604262306a36Sopenharmony_ci{
604362306a36Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
604462306a36Sopenharmony_ci	struct lpfc_hba   *phba = vport->phba;
604562306a36Sopenharmony_ci	char name[64];
604662306a36Sopenharmony_ci	uint32_t num, i;
604762306a36Sopenharmony_ci	bool pport_setup = false;
604862306a36Sopenharmony_ci
604962306a36Sopenharmony_ci	if (!lpfc_debugfs_enable)
605062306a36Sopenharmony_ci		return;
605162306a36Sopenharmony_ci
605262306a36Sopenharmony_ci	/* Setup lpfc root directory */
605362306a36Sopenharmony_ci	if (!lpfc_debugfs_root) {
605462306a36Sopenharmony_ci		lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL);
605562306a36Sopenharmony_ci		atomic_set(&lpfc_debugfs_hba_count, 0);
605662306a36Sopenharmony_ci	}
605762306a36Sopenharmony_ci	if (!lpfc_debugfs_start_time)
605862306a36Sopenharmony_ci		lpfc_debugfs_start_time = jiffies;
605962306a36Sopenharmony_ci
606062306a36Sopenharmony_ci	/* Setup funcX directory for specific HBA PCI function */
606162306a36Sopenharmony_ci	snprintf(name, sizeof(name), "fn%d", phba->brd_no);
606262306a36Sopenharmony_ci	if (!phba->hba_debugfs_root) {
606362306a36Sopenharmony_ci		pport_setup = true;
606462306a36Sopenharmony_ci		phba->hba_debugfs_root =
606562306a36Sopenharmony_ci			debugfs_create_dir(name, lpfc_debugfs_root);
606662306a36Sopenharmony_ci		atomic_inc(&lpfc_debugfs_hba_count);
606762306a36Sopenharmony_ci		atomic_set(&phba->debugfs_vport_count, 0);
606862306a36Sopenharmony_ci
606962306a36Sopenharmony_ci		/* Multi-XRI pools */
607062306a36Sopenharmony_ci		snprintf(name, sizeof(name), "multixripools");
607162306a36Sopenharmony_ci		phba->debug_multixri_pools =
607262306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG | 0644,
607362306a36Sopenharmony_ci					    phba->hba_debugfs_root,
607462306a36Sopenharmony_ci					    phba,
607562306a36Sopenharmony_ci					    &lpfc_debugfs_op_multixripools);
607662306a36Sopenharmony_ci		if (IS_ERR(phba->debug_multixri_pools)) {
607762306a36Sopenharmony_ci			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
607862306a36Sopenharmony_ci					 "0527 Cannot create debugfs multixripools\n");
607962306a36Sopenharmony_ci			goto debug_failed;
608062306a36Sopenharmony_ci		}
608162306a36Sopenharmony_ci
608262306a36Sopenharmony_ci		/* Congestion Info Buffer */
608362306a36Sopenharmony_ci		scnprintf(name, sizeof(name), "cgn_buffer");
608462306a36Sopenharmony_ci		phba->debug_cgn_buffer =
608562306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG | 0644,
608662306a36Sopenharmony_ci					    phba->hba_debugfs_root,
608762306a36Sopenharmony_ci					    phba, &lpfc_cgn_buffer_op);
608862306a36Sopenharmony_ci		if (IS_ERR(phba->debug_cgn_buffer)) {
608962306a36Sopenharmony_ci			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
609062306a36Sopenharmony_ci					 "6527 Cannot create debugfs "
609162306a36Sopenharmony_ci					 "cgn_buffer\n");
609262306a36Sopenharmony_ci			goto debug_failed;
609362306a36Sopenharmony_ci		}
609462306a36Sopenharmony_ci
609562306a36Sopenharmony_ci		/* RX Monitor */
609662306a36Sopenharmony_ci		scnprintf(name, sizeof(name), "rx_monitor");
609762306a36Sopenharmony_ci		phba->debug_rx_monitor =
609862306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG | 0644,
609962306a36Sopenharmony_ci					    phba->hba_debugfs_root,
610062306a36Sopenharmony_ci					    phba, &lpfc_rx_monitor_op);
610162306a36Sopenharmony_ci		if (IS_ERR(phba->debug_rx_monitor)) {
610262306a36Sopenharmony_ci			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
610362306a36Sopenharmony_ci					 "6528 Cannot create debugfs "
610462306a36Sopenharmony_ci					 "rx_monitor\n");
610562306a36Sopenharmony_ci			goto debug_failed;
610662306a36Sopenharmony_ci		}
610762306a36Sopenharmony_ci
610862306a36Sopenharmony_ci		/* RAS log */
610962306a36Sopenharmony_ci		snprintf(name, sizeof(name), "ras_log");
611062306a36Sopenharmony_ci		phba->debug_ras_log =
611162306a36Sopenharmony_ci			debugfs_create_file(name, 0644,
611262306a36Sopenharmony_ci					    phba->hba_debugfs_root,
611362306a36Sopenharmony_ci					    phba, &lpfc_debugfs_ras_log);
611462306a36Sopenharmony_ci		if (IS_ERR(phba->debug_ras_log)) {
611562306a36Sopenharmony_ci			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
611662306a36Sopenharmony_ci					 "6148 Cannot create debugfs"
611762306a36Sopenharmony_ci					 " ras_log\n");
611862306a36Sopenharmony_ci			goto debug_failed;
611962306a36Sopenharmony_ci		}
612062306a36Sopenharmony_ci
612162306a36Sopenharmony_ci		/* Setup hbqinfo */
612262306a36Sopenharmony_ci		snprintf(name, sizeof(name), "hbqinfo");
612362306a36Sopenharmony_ci		phba->debug_hbqinfo =
612462306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG | 0644,
612562306a36Sopenharmony_ci					    phba->hba_debugfs_root,
612662306a36Sopenharmony_ci					    phba, &lpfc_debugfs_op_hbqinfo);
612762306a36Sopenharmony_ci
612862306a36Sopenharmony_ci#ifdef LPFC_HDWQ_LOCK_STAT
612962306a36Sopenharmony_ci		/* Setup lockstat */
613062306a36Sopenharmony_ci		snprintf(name, sizeof(name), "lockstat");
613162306a36Sopenharmony_ci		phba->debug_lockstat =
613262306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG | 0644,
613362306a36Sopenharmony_ci					    phba->hba_debugfs_root,
613462306a36Sopenharmony_ci					    phba, &lpfc_debugfs_op_lockstat);
613562306a36Sopenharmony_ci		if (IS_ERR(phba->debug_lockstat)) {
613662306a36Sopenharmony_ci			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
613762306a36Sopenharmony_ci					 "4610 Can't create debugfs lockstat\n");
613862306a36Sopenharmony_ci			goto debug_failed;
613962306a36Sopenharmony_ci		}
614062306a36Sopenharmony_ci#endif
614162306a36Sopenharmony_ci
614262306a36Sopenharmony_ci		/* Setup dumpHBASlim */
614362306a36Sopenharmony_ci		if (phba->sli_rev < LPFC_SLI_REV4) {
614462306a36Sopenharmony_ci			snprintf(name, sizeof(name), "dumpHBASlim");
614562306a36Sopenharmony_ci			phba->debug_dumpHBASlim =
614662306a36Sopenharmony_ci				debugfs_create_file(name,
614762306a36Sopenharmony_ci					S_IFREG|S_IRUGO|S_IWUSR,
614862306a36Sopenharmony_ci					phba->hba_debugfs_root,
614962306a36Sopenharmony_ci					phba, &lpfc_debugfs_op_dumpHBASlim);
615062306a36Sopenharmony_ci		} else
615162306a36Sopenharmony_ci			phba->debug_dumpHBASlim = NULL;
615262306a36Sopenharmony_ci
615362306a36Sopenharmony_ci		/* Setup dumpHostSlim */
615462306a36Sopenharmony_ci		if (phba->sli_rev < LPFC_SLI_REV4) {
615562306a36Sopenharmony_ci			snprintf(name, sizeof(name), "dumpHostSlim");
615662306a36Sopenharmony_ci			phba->debug_dumpHostSlim =
615762306a36Sopenharmony_ci				debugfs_create_file(name,
615862306a36Sopenharmony_ci					S_IFREG|S_IRUGO|S_IWUSR,
615962306a36Sopenharmony_ci					phba->hba_debugfs_root,
616062306a36Sopenharmony_ci					phba, &lpfc_debugfs_op_dumpHostSlim);
616162306a36Sopenharmony_ci		} else
616262306a36Sopenharmony_ci			phba->debug_dumpHostSlim = NULL;
616362306a36Sopenharmony_ci
616462306a36Sopenharmony_ci		/* Setup DIF Error Injections */
616562306a36Sopenharmony_ci		snprintf(name, sizeof(name), "InjErrLBA");
616662306a36Sopenharmony_ci		phba->debug_InjErrLBA =
616762306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
616862306a36Sopenharmony_ci			phba->hba_debugfs_root,
616962306a36Sopenharmony_ci			phba, &lpfc_debugfs_op_dif_err);
617062306a36Sopenharmony_ci		phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
617162306a36Sopenharmony_ci
617262306a36Sopenharmony_ci		snprintf(name, sizeof(name), "InjErrNPortID");
617362306a36Sopenharmony_ci		phba->debug_InjErrNPortID =
617462306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
617562306a36Sopenharmony_ci			phba->hba_debugfs_root,
617662306a36Sopenharmony_ci			phba, &lpfc_debugfs_op_dif_err);
617762306a36Sopenharmony_ci
617862306a36Sopenharmony_ci		snprintf(name, sizeof(name), "InjErrWWPN");
617962306a36Sopenharmony_ci		phba->debug_InjErrWWPN =
618062306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
618162306a36Sopenharmony_ci			phba->hba_debugfs_root,
618262306a36Sopenharmony_ci			phba, &lpfc_debugfs_op_dif_err);
618362306a36Sopenharmony_ci
618462306a36Sopenharmony_ci		snprintf(name, sizeof(name), "writeGuardInjErr");
618562306a36Sopenharmony_ci		phba->debug_writeGuard =
618662306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
618762306a36Sopenharmony_ci			phba->hba_debugfs_root,
618862306a36Sopenharmony_ci			phba, &lpfc_debugfs_op_dif_err);
618962306a36Sopenharmony_ci
619062306a36Sopenharmony_ci		snprintf(name, sizeof(name), "writeAppInjErr");
619162306a36Sopenharmony_ci		phba->debug_writeApp =
619262306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
619362306a36Sopenharmony_ci			phba->hba_debugfs_root,
619462306a36Sopenharmony_ci			phba, &lpfc_debugfs_op_dif_err);
619562306a36Sopenharmony_ci
619662306a36Sopenharmony_ci		snprintf(name, sizeof(name), "writeRefInjErr");
619762306a36Sopenharmony_ci		phba->debug_writeRef =
619862306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
619962306a36Sopenharmony_ci			phba->hba_debugfs_root,
620062306a36Sopenharmony_ci			phba, &lpfc_debugfs_op_dif_err);
620162306a36Sopenharmony_ci
620262306a36Sopenharmony_ci		snprintf(name, sizeof(name), "readGuardInjErr");
620362306a36Sopenharmony_ci		phba->debug_readGuard =
620462306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
620562306a36Sopenharmony_ci			phba->hba_debugfs_root,
620662306a36Sopenharmony_ci			phba, &lpfc_debugfs_op_dif_err);
620762306a36Sopenharmony_ci
620862306a36Sopenharmony_ci		snprintf(name, sizeof(name), "readAppInjErr");
620962306a36Sopenharmony_ci		phba->debug_readApp =
621062306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
621162306a36Sopenharmony_ci			phba->hba_debugfs_root,
621262306a36Sopenharmony_ci			phba, &lpfc_debugfs_op_dif_err);
621362306a36Sopenharmony_ci
621462306a36Sopenharmony_ci		snprintf(name, sizeof(name), "readRefInjErr");
621562306a36Sopenharmony_ci		phba->debug_readRef =
621662306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
621762306a36Sopenharmony_ci			phba->hba_debugfs_root,
621862306a36Sopenharmony_ci			phba, &lpfc_debugfs_op_dif_err);
621962306a36Sopenharmony_ci
622062306a36Sopenharmony_ci		/* Setup slow ring trace */
622162306a36Sopenharmony_ci		if (lpfc_debugfs_max_slow_ring_trc) {
622262306a36Sopenharmony_ci			num = lpfc_debugfs_max_slow_ring_trc - 1;
622362306a36Sopenharmony_ci			if (num & lpfc_debugfs_max_slow_ring_trc) {
622462306a36Sopenharmony_ci				/* Change to be a power of 2 */
622562306a36Sopenharmony_ci				num = lpfc_debugfs_max_slow_ring_trc;
622662306a36Sopenharmony_ci				i = 0;
622762306a36Sopenharmony_ci				while (num > 1) {
622862306a36Sopenharmony_ci					num = num >> 1;
622962306a36Sopenharmony_ci					i++;
623062306a36Sopenharmony_ci				}
623162306a36Sopenharmony_ci				lpfc_debugfs_max_slow_ring_trc = (1 << i);
623262306a36Sopenharmony_ci				pr_err("lpfc_debugfs_max_disc_trc changed to "
623362306a36Sopenharmony_ci				       "%d\n", lpfc_debugfs_max_disc_trc);
623462306a36Sopenharmony_ci			}
623562306a36Sopenharmony_ci		}
623662306a36Sopenharmony_ci
623762306a36Sopenharmony_ci		snprintf(name, sizeof(name), "slow_ring_trace");
623862306a36Sopenharmony_ci		phba->debug_slow_ring_trc =
623962306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
624062306a36Sopenharmony_ci				 phba->hba_debugfs_root,
624162306a36Sopenharmony_ci				 phba, &lpfc_debugfs_op_slow_ring_trc);
624262306a36Sopenharmony_ci		if (!phba->slow_ring_trc) {
624362306a36Sopenharmony_ci			phba->slow_ring_trc = kcalloc(
624462306a36Sopenharmony_ci				lpfc_debugfs_max_slow_ring_trc,
624562306a36Sopenharmony_ci				sizeof(struct lpfc_debugfs_trc),
624662306a36Sopenharmony_ci				GFP_KERNEL);
624762306a36Sopenharmony_ci			if (!phba->slow_ring_trc) {
624862306a36Sopenharmony_ci				lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
624962306a36Sopenharmony_ci						 "0416 Cannot create debugfs "
625062306a36Sopenharmony_ci						 "slow_ring buffer\n");
625162306a36Sopenharmony_ci				goto debug_failed;
625262306a36Sopenharmony_ci			}
625362306a36Sopenharmony_ci			atomic_set(&phba->slow_ring_trc_cnt, 0);
625462306a36Sopenharmony_ci		}
625562306a36Sopenharmony_ci
625662306a36Sopenharmony_ci		snprintf(name, sizeof(name), "nvmeio_trc");
625762306a36Sopenharmony_ci		phba->debug_nvmeio_trc =
625862306a36Sopenharmony_ci			debugfs_create_file(name, 0644,
625962306a36Sopenharmony_ci					    phba->hba_debugfs_root,
626062306a36Sopenharmony_ci					    phba, &lpfc_debugfs_op_nvmeio_trc);
626162306a36Sopenharmony_ci
626262306a36Sopenharmony_ci		atomic_set(&phba->nvmeio_trc_cnt, 0);
626362306a36Sopenharmony_ci		if (lpfc_debugfs_max_nvmeio_trc) {
626462306a36Sopenharmony_ci			num = lpfc_debugfs_max_nvmeio_trc - 1;
626562306a36Sopenharmony_ci			if (num & lpfc_debugfs_max_disc_trc) {
626662306a36Sopenharmony_ci				/* Change to be a power of 2 */
626762306a36Sopenharmony_ci				num = lpfc_debugfs_max_nvmeio_trc;
626862306a36Sopenharmony_ci				i = 0;
626962306a36Sopenharmony_ci				while (num > 1) {
627062306a36Sopenharmony_ci					num = num >> 1;
627162306a36Sopenharmony_ci					i++;
627262306a36Sopenharmony_ci				}
627362306a36Sopenharmony_ci				lpfc_debugfs_max_nvmeio_trc = (1 << i);
627462306a36Sopenharmony_ci				lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
627562306a36Sopenharmony_ci						"0575 lpfc_debugfs_max_nvmeio_trc "
627662306a36Sopenharmony_ci						"changed to %d\n",
627762306a36Sopenharmony_ci						lpfc_debugfs_max_nvmeio_trc);
627862306a36Sopenharmony_ci			}
627962306a36Sopenharmony_ci			phba->nvmeio_trc_size = lpfc_debugfs_max_nvmeio_trc;
628062306a36Sopenharmony_ci
628162306a36Sopenharmony_ci			/* Allocate trace buffer and initialize */
628262306a36Sopenharmony_ci			phba->nvmeio_trc = kzalloc(
628362306a36Sopenharmony_ci				(sizeof(struct lpfc_debugfs_nvmeio_trc) *
628462306a36Sopenharmony_ci				phba->nvmeio_trc_size), GFP_KERNEL);
628562306a36Sopenharmony_ci
628662306a36Sopenharmony_ci			if (!phba->nvmeio_trc) {
628762306a36Sopenharmony_ci				lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
628862306a36Sopenharmony_ci						"0576 Cannot create debugfs "
628962306a36Sopenharmony_ci						"nvmeio_trc buffer\n");
629062306a36Sopenharmony_ci				goto nvmeio_off;
629162306a36Sopenharmony_ci			}
629262306a36Sopenharmony_ci			phba->nvmeio_trc_on = 1;
629362306a36Sopenharmony_ci			phba->nvmeio_trc_output_idx = 0;
629462306a36Sopenharmony_ci			phba->nvmeio_trc = NULL;
629562306a36Sopenharmony_ci		} else {
629662306a36Sopenharmony_cinvmeio_off:
629762306a36Sopenharmony_ci			phba->nvmeio_trc_size = 0;
629862306a36Sopenharmony_ci			phba->nvmeio_trc_on = 0;
629962306a36Sopenharmony_ci			phba->nvmeio_trc_output_idx = 0;
630062306a36Sopenharmony_ci			phba->nvmeio_trc = NULL;
630162306a36Sopenharmony_ci		}
630262306a36Sopenharmony_ci	}
630362306a36Sopenharmony_ci
630462306a36Sopenharmony_ci	snprintf(name, sizeof(name), "vport%d", vport->vpi);
630562306a36Sopenharmony_ci	if (!vport->vport_debugfs_root) {
630662306a36Sopenharmony_ci		vport->vport_debugfs_root =
630762306a36Sopenharmony_ci			debugfs_create_dir(name, phba->hba_debugfs_root);
630862306a36Sopenharmony_ci		atomic_inc(&phba->debugfs_vport_count);
630962306a36Sopenharmony_ci	}
631062306a36Sopenharmony_ci
631162306a36Sopenharmony_ci	if (lpfc_debugfs_max_disc_trc) {
631262306a36Sopenharmony_ci		num = lpfc_debugfs_max_disc_trc - 1;
631362306a36Sopenharmony_ci		if (num & lpfc_debugfs_max_disc_trc) {
631462306a36Sopenharmony_ci			/* Change to be a power of 2 */
631562306a36Sopenharmony_ci			num = lpfc_debugfs_max_disc_trc;
631662306a36Sopenharmony_ci			i = 0;
631762306a36Sopenharmony_ci			while (num > 1) {
631862306a36Sopenharmony_ci				num = num >> 1;
631962306a36Sopenharmony_ci				i++;
632062306a36Sopenharmony_ci			}
632162306a36Sopenharmony_ci			lpfc_debugfs_max_disc_trc = (1 << i);
632262306a36Sopenharmony_ci			pr_err("lpfc_debugfs_max_disc_trc changed to %d\n",
632362306a36Sopenharmony_ci			       lpfc_debugfs_max_disc_trc);
632462306a36Sopenharmony_ci		}
632562306a36Sopenharmony_ci	}
632662306a36Sopenharmony_ci
632762306a36Sopenharmony_ci	vport->disc_trc = kzalloc(
632862306a36Sopenharmony_ci		(sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc),
632962306a36Sopenharmony_ci		GFP_KERNEL);
633062306a36Sopenharmony_ci
633162306a36Sopenharmony_ci	if (!vport->disc_trc) {
633262306a36Sopenharmony_ci		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
633362306a36Sopenharmony_ci				 "0418 Cannot create debugfs disc trace "
633462306a36Sopenharmony_ci				 "buffer\n");
633562306a36Sopenharmony_ci		goto debug_failed;
633662306a36Sopenharmony_ci	}
633762306a36Sopenharmony_ci	atomic_set(&vport->disc_trc_cnt, 0);
633862306a36Sopenharmony_ci
633962306a36Sopenharmony_ci	snprintf(name, sizeof(name), "discovery_trace");
634062306a36Sopenharmony_ci	vport->debug_disc_trc =
634162306a36Sopenharmony_ci		debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
634262306a36Sopenharmony_ci				 vport->vport_debugfs_root,
634362306a36Sopenharmony_ci				 vport, &lpfc_debugfs_op_disc_trc);
634462306a36Sopenharmony_ci	snprintf(name, sizeof(name), "nodelist");
634562306a36Sopenharmony_ci	vport->debug_nodelist =
634662306a36Sopenharmony_ci		debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
634762306a36Sopenharmony_ci				 vport->vport_debugfs_root,
634862306a36Sopenharmony_ci				 vport, &lpfc_debugfs_op_nodelist);
634962306a36Sopenharmony_ci
635062306a36Sopenharmony_ci	snprintf(name, sizeof(name), "nvmestat");
635162306a36Sopenharmony_ci	vport->debug_nvmestat =
635262306a36Sopenharmony_ci		debugfs_create_file(name, 0644,
635362306a36Sopenharmony_ci				    vport->vport_debugfs_root,
635462306a36Sopenharmony_ci				    vport, &lpfc_debugfs_op_nvmestat);
635562306a36Sopenharmony_ci
635662306a36Sopenharmony_ci	snprintf(name, sizeof(name), "scsistat");
635762306a36Sopenharmony_ci	vport->debug_scsistat =
635862306a36Sopenharmony_ci		debugfs_create_file(name, 0644,
635962306a36Sopenharmony_ci				    vport->vport_debugfs_root,
636062306a36Sopenharmony_ci				    vport, &lpfc_debugfs_op_scsistat);
636162306a36Sopenharmony_ci	if (IS_ERR(vport->debug_scsistat)) {
636262306a36Sopenharmony_ci		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
636362306a36Sopenharmony_ci				 "4611 Cannot create debugfs scsistat\n");
636462306a36Sopenharmony_ci		goto debug_failed;
636562306a36Sopenharmony_ci	}
636662306a36Sopenharmony_ci
636762306a36Sopenharmony_ci	snprintf(name, sizeof(name), "ioktime");
636862306a36Sopenharmony_ci	vport->debug_ioktime =
636962306a36Sopenharmony_ci		debugfs_create_file(name, 0644,
637062306a36Sopenharmony_ci				    vport->vport_debugfs_root,
637162306a36Sopenharmony_ci				    vport, &lpfc_debugfs_op_ioktime);
637262306a36Sopenharmony_ci	if (IS_ERR(vport->debug_ioktime)) {
637362306a36Sopenharmony_ci		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
637462306a36Sopenharmony_ci				 "0815 Cannot create debugfs ioktime\n");
637562306a36Sopenharmony_ci		goto debug_failed;
637662306a36Sopenharmony_ci	}
637762306a36Sopenharmony_ci
637862306a36Sopenharmony_ci	snprintf(name, sizeof(name), "hdwqstat");
637962306a36Sopenharmony_ci	vport->debug_hdwqstat =
638062306a36Sopenharmony_ci		debugfs_create_file(name, 0644,
638162306a36Sopenharmony_ci				    vport->vport_debugfs_root,
638262306a36Sopenharmony_ci				    vport, &lpfc_debugfs_op_hdwqstat);
638362306a36Sopenharmony_ci
638462306a36Sopenharmony_ci	/*
638562306a36Sopenharmony_ci	 * The following section is for additional directories/files for the
638662306a36Sopenharmony_ci	 * physical port.
638762306a36Sopenharmony_ci	 */
638862306a36Sopenharmony_ci
638962306a36Sopenharmony_ci	if (!pport_setup)
639062306a36Sopenharmony_ci		goto debug_failed;
639162306a36Sopenharmony_ci
639262306a36Sopenharmony_ci	/*
639362306a36Sopenharmony_ci	 * iDiag debugfs root entry points for SLI4 device only
639462306a36Sopenharmony_ci	 */
639562306a36Sopenharmony_ci	if (phba->sli_rev < LPFC_SLI_REV4)
639662306a36Sopenharmony_ci		goto debug_failed;
639762306a36Sopenharmony_ci
639862306a36Sopenharmony_ci	snprintf(name, sizeof(name), "iDiag");
639962306a36Sopenharmony_ci	if (!phba->idiag_root) {
640062306a36Sopenharmony_ci		phba->idiag_root =
640162306a36Sopenharmony_ci			debugfs_create_dir(name, phba->hba_debugfs_root);
640262306a36Sopenharmony_ci		/* Initialize iDiag data structure */
640362306a36Sopenharmony_ci		memset(&idiag, 0, sizeof(idiag));
640462306a36Sopenharmony_ci	}
640562306a36Sopenharmony_ci
640662306a36Sopenharmony_ci	/* iDiag read PCI config space */
640762306a36Sopenharmony_ci	snprintf(name, sizeof(name), "pciCfg");
640862306a36Sopenharmony_ci	if (!phba->idiag_pci_cfg) {
640962306a36Sopenharmony_ci		phba->idiag_pci_cfg =
641062306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
641162306a36Sopenharmony_ci				phba->idiag_root, phba, &lpfc_idiag_op_pciCfg);
641262306a36Sopenharmony_ci		idiag.offset.last_rd = 0;
641362306a36Sopenharmony_ci	}
641462306a36Sopenharmony_ci
641562306a36Sopenharmony_ci	/* iDiag PCI BAR access */
641662306a36Sopenharmony_ci	snprintf(name, sizeof(name), "barAcc");
641762306a36Sopenharmony_ci	if (!phba->idiag_bar_acc) {
641862306a36Sopenharmony_ci		phba->idiag_bar_acc =
641962306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
642062306a36Sopenharmony_ci				phba->idiag_root, phba, &lpfc_idiag_op_barAcc);
642162306a36Sopenharmony_ci		idiag.offset.last_rd = 0;
642262306a36Sopenharmony_ci	}
642362306a36Sopenharmony_ci
642462306a36Sopenharmony_ci	/* iDiag get PCI function queue information */
642562306a36Sopenharmony_ci	snprintf(name, sizeof(name), "queInfo");
642662306a36Sopenharmony_ci	if (!phba->idiag_que_info) {
642762306a36Sopenharmony_ci		phba->idiag_que_info =
642862306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO,
642962306a36Sopenharmony_ci			phba->idiag_root, phba, &lpfc_idiag_op_queInfo);
643062306a36Sopenharmony_ci	}
643162306a36Sopenharmony_ci
643262306a36Sopenharmony_ci	/* iDiag access PCI function queue */
643362306a36Sopenharmony_ci	snprintf(name, sizeof(name), "queAcc");
643462306a36Sopenharmony_ci	if (!phba->idiag_que_acc) {
643562306a36Sopenharmony_ci		phba->idiag_que_acc =
643662306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
643762306a36Sopenharmony_ci				phba->idiag_root, phba, &lpfc_idiag_op_queAcc);
643862306a36Sopenharmony_ci	}
643962306a36Sopenharmony_ci
644062306a36Sopenharmony_ci	/* iDiag access PCI function doorbell registers */
644162306a36Sopenharmony_ci	snprintf(name, sizeof(name), "drbAcc");
644262306a36Sopenharmony_ci	if (!phba->idiag_drb_acc) {
644362306a36Sopenharmony_ci		phba->idiag_drb_acc =
644462306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
644562306a36Sopenharmony_ci				phba->idiag_root, phba, &lpfc_idiag_op_drbAcc);
644662306a36Sopenharmony_ci	}
644762306a36Sopenharmony_ci
644862306a36Sopenharmony_ci	/* iDiag access PCI function control registers */
644962306a36Sopenharmony_ci	snprintf(name, sizeof(name), "ctlAcc");
645062306a36Sopenharmony_ci	if (!phba->idiag_ctl_acc) {
645162306a36Sopenharmony_ci		phba->idiag_ctl_acc =
645262306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
645362306a36Sopenharmony_ci				phba->idiag_root, phba, &lpfc_idiag_op_ctlAcc);
645462306a36Sopenharmony_ci	}
645562306a36Sopenharmony_ci
645662306a36Sopenharmony_ci	/* iDiag access mbox commands */
645762306a36Sopenharmony_ci	snprintf(name, sizeof(name), "mbxAcc");
645862306a36Sopenharmony_ci	if (!phba->idiag_mbx_acc) {
645962306a36Sopenharmony_ci		phba->idiag_mbx_acc =
646062306a36Sopenharmony_ci			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
646162306a36Sopenharmony_ci				phba->idiag_root, phba, &lpfc_idiag_op_mbxAcc);
646262306a36Sopenharmony_ci	}
646362306a36Sopenharmony_ci
646462306a36Sopenharmony_ci	/* iDiag extents access commands */
646562306a36Sopenharmony_ci	if (phba->sli4_hba.extents_in_use) {
646662306a36Sopenharmony_ci		snprintf(name, sizeof(name), "extAcc");
646762306a36Sopenharmony_ci		if (!phba->idiag_ext_acc) {
646862306a36Sopenharmony_ci			phba->idiag_ext_acc =
646962306a36Sopenharmony_ci				debugfs_create_file(name,
647062306a36Sopenharmony_ci						    S_IFREG|S_IRUGO|S_IWUSR,
647162306a36Sopenharmony_ci						    phba->idiag_root, phba,
647262306a36Sopenharmony_ci						    &lpfc_idiag_op_extAcc);
647362306a36Sopenharmony_ci		}
647462306a36Sopenharmony_ci	}
647562306a36Sopenharmony_ci
647662306a36Sopenharmony_cidebug_failed:
647762306a36Sopenharmony_ci	return;
647862306a36Sopenharmony_ci#endif
647962306a36Sopenharmony_ci}
648062306a36Sopenharmony_ci
648162306a36Sopenharmony_ci/**
648262306a36Sopenharmony_ci * lpfc_debugfs_terminate -  Tear down debugfs infrastructure for this vport
648362306a36Sopenharmony_ci * @vport: The vport pointer to remove from debugfs.
648462306a36Sopenharmony_ci *
648562306a36Sopenharmony_ci * Description:
648662306a36Sopenharmony_ci * When Debugfs is configured this routine removes debugfs file system elements
648762306a36Sopenharmony_ci * that are specific to this vport. It also checks to see if there are any
648862306a36Sopenharmony_ci * users left for the debugfs directories associated with the HBA and driver. If
648962306a36Sopenharmony_ci * this is the last user of the HBA directory or driver directory then it will
649062306a36Sopenharmony_ci * remove those from the debugfs infrastructure as well.
649162306a36Sopenharmony_ci **/
649262306a36Sopenharmony_ciinline void
649362306a36Sopenharmony_cilpfc_debugfs_terminate(struct lpfc_vport *vport)
649462306a36Sopenharmony_ci{
649562306a36Sopenharmony_ci#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
649662306a36Sopenharmony_ci	struct lpfc_hba   *phba = vport->phba;
649762306a36Sopenharmony_ci
649862306a36Sopenharmony_ci	kfree(vport->disc_trc);
649962306a36Sopenharmony_ci	vport->disc_trc = NULL;
650062306a36Sopenharmony_ci
650162306a36Sopenharmony_ci	debugfs_remove(vport->debug_disc_trc); /* discovery_trace */
650262306a36Sopenharmony_ci	vport->debug_disc_trc = NULL;
650362306a36Sopenharmony_ci
650462306a36Sopenharmony_ci	debugfs_remove(vport->debug_nodelist); /* nodelist */
650562306a36Sopenharmony_ci	vport->debug_nodelist = NULL;
650662306a36Sopenharmony_ci
650762306a36Sopenharmony_ci	debugfs_remove(vport->debug_nvmestat); /* nvmestat */
650862306a36Sopenharmony_ci	vport->debug_nvmestat = NULL;
650962306a36Sopenharmony_ci
651062306a36Sopenharmony_ci	debugfs_remove(vport->debug_scsistat); /* scsistat */
651162306a36Sopenharmony_ci	vport->debug_scsistat = NULL;
651262306a36Sopenharmony_ci
651362306a36Sopenharmony_ci	debugfs_remove(vport->debug_ioktime); /* ioktime */
651462306a36Sopenharmony_ci	vport->debug_ioktime = NULL;
651562306a36Sopenharmony_ci
651662306a36Sopenharmony_ci	debugfs_remove(vport->debug_hdwqstat); /* hdwqstat */
651762306a36Sopenharmony_ci	vport->debug_hdwqstat = NULL;
651862306a36Sopenharmony_ci
651962306a36Sopenharmony_ci	if (vport->vport_debugfs_root) {
652062306a36Sopenharmony_ci		debugfs_remove(vport->vport_debugfs_root); /* vportX */
652162306a36Sopenharmony_ci		vport->vport_debugfs_root = NULL;
652262306a36Sopenharmony_ci		atomic_dec(&phba->debugfs_vport_count);
652362306a36Sopenharmony_ci	}
652462306a36Sopenharmony_ci
652562306a36Sopenharmony_ci	if (atomic_read(&phba->debugfs_vport_count) == 0) {
652662306a36Sopenharmony_ci
652762306a36Sopenharmony_ci		debugfs_remove(phba->debug_multixri_pools); /* multixripools*/
652862306a36Sopenharmony_ci		phba->debug_multixri_pools = NULL;
652962306a36Sopenharmony_ci
653062306a36Sopenharmony_ci		debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */
653162306a36Sopenharmony_ci		phba->debug_hbqinfo = NULL;
653262306a36Sopenharmony_ci
653362306a36Sopenharmony_ci		debugfs_remove(phba->debug_cgn_buffer);
653462306a36Sopenharmony_ci		phba->debug_cgn_buffer = NULL;
653562306a36Sopenharmony_ci
653662306a36Sopenharmony_ci		debugfs_remove(phba->debug_rx_monitor);
653762306a36Sopenharmony_ci		phba->debug_rx_monitor = NULL;
653862306a36Sopenharmony_ci
653962306a36Sopenharmony_ci		debugfs_remove(phba->debug_ras_log);
654062306a36Sopenharmony_ci		phba->debug_ras_log = NULL;
654162306a36Sopenharmony_ci
654262306a36Sopenharmony_ci#ifdef LPFC_HDWQ_LOCK_STAT
654362306a36Sopenharmony_ci		debugfs_remove(phba->debug_lockstat); /* lockstat */
654462306a36Sopenharmony_ci		phba->debug_lockstat = NULL;
654562306a36Sopenharmony_ci#endif
654662306a36Sopenharmony_ci		debugfs_remove(phba->debug_dumpHBASlim); /* HBASlim */
654762306a36Sopenharmony_ci		phba->debug_dumpHBASlim = NULL;
654862306a36Sopenharmony_ci
654962306a36Sopenharmony_ci		debugfs_remove(phba->debug_dumpHostSlim); /* HostSlim */
655062306a36Sopenharmony_ci		phba->debug_dumpHostSlim = NULL;
655162306a36Sopenharmony_ci
655262306a36Sopenharmony_ci		debugfs_remove(phba->debug_InjErrLBA); /* InjErrLBA */
655362306a36Sopenharmony_ci		phba->debug_InjErrLBA = NULL;
655462306a36Sopenharmony_ci
655562306a36Sopenharmony_ci		debugfs_remove(phba->debug_InjErrNPortID);
655662306a36Sopenharmony_ci		phba->debug_InjErrNPortID = NULL;
655762306a36Sopenharmony_ci
655862306a36Sopenharmony_ci		debugfs_remove(phba->debug_InjErrWWPN); /* InjErrWWPN */
655962306a36Sopenharmony_ci		phba->debug_InjErrWWPN = NULL;
656062306a36Sopenharmony_ci
656162306a36Sopenharmony_ci		debugfs_remove(phba->debug_writeGuard); /* writeGuard */
656262306a36Sopenharmony_ci		phba->debug_writeGuard = NULL;
656362306a36Sopenharmony_ci
656462306a36Sopenharmony_ci		debugfs_remove(phba->debug_writeApp); /* writeApp */
656562306a36Sopenharmony_ci		phba->debug_writeApp = NULL;
656662306a36Sopenharmony_ci
656762306a36Sopenharmony_ci		debugfs_remove(phba->debug_writeRef); /* writeRef */
656862306a36Sopenharmony_ci		phba->debug_writeRef = NULL;
656962306a36Sopenharmony_ci
657062306a36Sopenharmony_ci		debugfs_remove(phba->debug_readGuard); /* readGuard */
657162306a36Sopenharmony_ci		phba->debug_readGuard = NULL;
657262306a36Sopenharmony_ci
657362306a36Sopenharmony_ci		debugfs_remove(phba->debug_readApp); /* readApp */
657462306a36Sopenharmony_ci		phba->debug_readApp = NULL;
657562306a36Sopenharmony_ci
657662306a36Sopenharmony_ci		debugfs_remove(phba->debug_readRef); /* readRef */
657762306a36Sopenharmony_ci		phba->debug_readRef = NULL;
657862306a36Sopenharmony_ci
657962306a36Sopenharmony_ci		kfree(phba->slow_ring_trc);
658062306a36Sopenharmony_ci		phba->slow_ring_trc = NULL;
658162306a36Sopenharmony_ci
658262306a36Sopenharmony_ci		/* slow_ring_trace */
658362306a36Sopenharmony_ci		debugfs_remove(phba->debug_slow_ring_trc);
658462306a36Sopenharmony_ci		phba->debug_slow_ring_trc = NULL;
658562306a36Sopenharmony_ci
658662306a36Sopenharmony_ci		debugfs_remove(phba->debug_nvmeio_trc);
658762306a36Sopenharmony_ci		phba->debug_nvmeio_trc = NULL;
658862306a36Sopenharmony_ci
658962306a36Sopenharmony_ci		kfree(phba->nvmeio_trc);
659062306a36Sopenharmony_ci		phba->nvmeio_trc = NULL;
659162306a36Sopenharmony_ci
659262306a36Sopenharmony_ci		/*
659362306a36Sopenharmony_ci		 * iDiag release
659462306a36Sopenharmony_ci		 */
659562306a36Sopenharmony_ci		if (phba->sli_rev == LPFC_SLI_REV4) {
659662306a36Sopenharmony_ci			/* iDiag extAcc */
659762306a36Sopenharmony_ci			debugfs_remove(phba->idiag_ext_acc);
659862306a36Sopenharmony_ci			phba->idiag_ext_acc = NULL;
659962306a36Sopenharmony_ci
660062306a36Sopenharmony_ci			/* iDiag mbxAcc */
660162306a36Sopenharmony_ci			debugfs_remove(phba->idiag_mbx_acc);
660262306a36Sopenharmony_ci			phba->idiag_mbx_acc = NULL;
660362306a36Sopenharmony_ci
660462306a36Sopenharmony_ci			/* iDiag ctlAcc */
660562306a36Sopenharmony_ci			debugfs_remove(phba->idiag_ctl_acc);
660662306a36Sopenharmony_ci			phba->idiag_ctl_acc = NULL;
660762306a36Sopenharmony_ci
660862306a36Sopenharmony_ci			/* iDiag drbAcc */
660962306a36Sopenharmony_ci			debugfs_remove(phba->idiag_drb_acc);
661062306a36Sopenharmony_ci			phba->idiag_drb_acc = NULL;
661162306a36Sopenharmony_ci
661262306a36Sopenharmony_ci			/* iDiag queAcc */
661362306a36Sopenharmony_ci			debugfs_remove(phba->idiag_que_acc);
661462306a36Sopenharmony_ci			phba->idiag_que_acc = NULL;
661562306a36Sopenharmony_ci
661662306a36Sopenharmony_ci			/* iDiag queInfo */
661762306a36Sopenharmony_ci			debugfs_remove(phba->idiag_que_info);
661862306a36Sopenharmony_ci			phba->idiag_que_info = NULL;
661962306a36Sopenharmony_ci
662062306a36Sopenharmony_ci			/* iDiag barAcc */
662162306a36Sopenharmony_ci			debugfs_remove(phba->idiag_bar_acc);
662262306a36Sopenharmony_ci			phba->idiag_bar_acc = NULL;
662362306a36Sopenharmony_ci
662462306a36Sopenharmony_ci			/* iDiag pciCfg */
662562306a36Sopenharmony_ci			debugfs_remove(phba->idiag_pci_cfg);
662662306a36Sopenharmony_ci			phba->idiag_pci_cfg = NULL;
662762306a36Sopenharmony_ci
662862306a36Sopenharmony_ci			/* Finally remove the iDiag debugfs root */
662962306a36Sopenharmony_ci			debugfs_remove(phba->idiag_root);
663062306a36Sopenharmony_ci			phba->idiag_root = NULL;
663162306a36Sopenharmony_ci		}
663262306a36Sopenharmony_ci
663362306a36Sopenharmony_ci		if (phba->hba_debugfs_root) {
663462306a36Sopenharmony_ci			debugfs_remove(phba->hba_debugfs_root); /* fnX */
663562306a36Sopenharmony_ci			phba->hba_debugfs_root = NULL;
663662306a36Sopenharmony_ci			atomic_dec(&lpfc_debugfs_hba_count);
663762306a36Sopenharmony_ci		}
663862306a36Sopenharmony_ci
663962306a36Sopenharmony_ci		if (atomic_read(&lpfc_debugfs_hba_count) == 0) {
664062306a36Sopenharmony_ci			debugfs_remove(lpfc_debugfs_root); /* lpfc */
664162306a36Sopenharmony_ci			lpfc_debugfs_root = NULL;
664262306a36Sopenharmony_ci		}
664362306a36Sopenharmony_ci	}
664462306a36Sopenharmony_ci#endif
664562306a36Sopenharmony_ci	return;
664662306a36Sopenharmony_ci}
664762306a36Sopenharmony_ci
664862306a36Sopenharmony_ci/*
664962306a36Sopenharmony_ci * Driver debug utility routines outside of debugfs. The debug utility
665062306a36Sopenharmony_ci * routines implemented here is intended to be used in the instrumented
665162306a36Sopenharmony_ci * debug driver for debugging host or port issues.
665262306a36Sopenharmony_ci */
665362306a36Sopenharmony_ci
665462306a36Sopenharmony_ci/**
665562306a36Sopenharmony_ci * lpfc_debug_dump_all_queues - dump all the queues with a hba
665662306a36Sopenharmony_ci * @phba: Pointer to HBA context object.
665762306a36Sopenharmony_ci *
665862306a36Sopenharmony_ci * This function dumps entries of all the queues asociated with the @phba.
665962306a36Sopenharmony_ci **/
666062306a36Sopenharmony_civoid
666162306a36Sopenharmony_cilpfc_debug_dump_all_queues(struct lpfc_hba *phba)
666262306a36Sopenharmony_ci{
666362306a36Sopenharmony_ci	int idx;
666462306a36Sopenharmony_ci
666562306a36Sopenharmony_ci	/*
666662306a36Sopenharmony_ci	 * Dump Work Queues (WQs)
666762306a36Sopenharmony_ci	 */
666862306a36Sopenharmony_ci	lpfc_debug_dump_wq(phba, DUMP_MBX, 0);
666962306a36Sopenharmony_ci	lpfc_debug_dump_wq(phba, DUMP_ELS, 0);
667062306a36Sopenharmony_ci	lpfc_debug_dump_wq(phba, DUMP_NVMELS, 0);
667162306a36Sopenharmony_ci
667262306a36Sopenharmony_ci	for (idx = 0; idx < phba->cfg_hdw_queue; idx++)
667362306a36Sopenharmony_ci		lpfc_debug_dump_wq(phba, DUMP_IO, idx);
667462306a36Sopenharmony_ci
667562306a36Sopenharmony_ci	lpfc_debug_dump_hdr_rq(phba);
667662306a36Sopenharmony_ci	lpfc_debug_dump_dat_rq(phba);
667762306a36Sopenharmony_ci	/*
667862306a36Sopenharmony_ci	 * Dump Complete Queues (CQs)
667962306a36Sopenharmony_ci	 */
668062306a36Sopenharmony_ci	lpfc_debug_dump_cq(phba, DUMP_MBX, 0);
668162306a36Sopenharmony_ci	lpfc_debug_dump_cq(phba, DUMP_ELS, 0);
668262306a36Sopenharmony_ci	lpfc_debug_dump_cq(phba, DUMP_NVMELS, 0);
668362306a36Sopenharmony_ci
668462306a36Sopenharmony_ci	for (idx = 0; idx < phba->cfg_hdw_queue; idx++)
668562306a36Sopenharmony_ci		lpfc_debug_dump_cq(phba, DUMP_IO, idx);
668662306a36Sopenharmony_ci
668762306a36Sopenharmony_ci	/*
668862306a36Sopenharmony_ci	 * Dump Event Queues (EQs)
668962306a36Sopenharmony_ci	 */
669062306a36Sopenharmony_ci	for (idx = 0; idx < phba->cfg_hdw_queue; idx++)
669162306a36Sopenharmony_ci		lpfc_debug_dump_hba_eq(phba, idx);
669262306a36Sopenharmony_ci}
6693