brintos

brintos / linux-shallow public Read only

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