blob: 2e6a68d9ea4feaef041a2ed1851d1a2fcb6676af [file] [log] [blame]
James Smart858c9f62007-06-17 19:56:39 -05001/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. *
James Smart0d041212019-01-28 11:14:41 -08004 * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
James Smart3e21d1c2018-05-04 20:37:59 -07005 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
James Smartf25e8e72015-04-07 15:07:28 -04006 * Copyright (C) 2007-2015 Emulex. All rights reserved. *
James Smart858c9f62007-06-17 19:56:39 -05007 * EMULEX and SLI are trademarks of Emulex. *
James Smartd080abe2017-02-12 13:52:39 -08008 * www.broadcom.com *
James Smart858c9f62007-06-17 19:56:39 -05009 * *
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>
Paul Gortmakeracf3368f2011-05-27 09:47:43 -040025#include <linux/module.h>
James Smart858c9f62007-06-17 19:56:39 -050026#include <linux/dma-mapping.h>
27#include <linux/idr.h>
28#include <linux/interrupt.h>
29#include <linux/kthread.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090030#include <linux/slab.h>
James Smart858c9f62007-06-17 19:56:39 -050031#include <linux/pci.h>
32#include <linux/spinlock.h>
33#include <linux/ctype.h>
James Smart9e2edb42019-10-25 11:25:30 -070034#include <linux/vmalloc.h>
James Smart858c9f62007-06-17 19:56:39 -050035
36#include <scsi/scsi.h>
37#include <scsi/scsi_device.h>
38#include <scsi/scsi_host.h>
39#include <scsi/scsi_transport_fc.h>
James Smartbd2cdd52017-02-12 13:52:33 -080040#include <scsi/fc/fc_fs.h>
41
42#include <linux/nvme-fc-driver.h>
James Smart858c9f62007-06-17 19:56:39 -050043
James Smartda0436e2009-05-22 14:51:39 -040044#include "lpfc_hw4.h"
James Smart858c9f62007-06-17 19:56:39 -050045#include "lpfc_hw.h"
46#include "lpfc_sli.h"
James Smartda0436e2009-05-22 14:51:39 -040047#include "lpfc_sli4.h"
James Smartea2151b2008-09-07 11:52:10 -040048#include "lpfc_nl.h"
James Smart858c9f62007-06-17 19:56:39 -050049#include "lpfc_disc.h"
James Smart858c9f62007-06-17 19:56:39 -050050#include "lpfc.h"
James Smartbd2cdd52017-02-12 13:52:33 -080051#include "lpfc_scsi.h"
52#include "lpfc_nvme.h"
James Smart2b65e182017-02-12 13:52:38 -080053#include "lpfc_nvmet.h"
James Smart858c9f62007-06-17 19:56:39 -050054#include "lpfc_logmsg.h"
55#include "lpfc_crtn.h"
56#include "lpfc_vport.h"
57#include "lpfc_version.h"
James Smartc95d6c62008-01-11 01:53:23 -050058#include "lpfc_compat.h"
James Smart858c9f62007-06-17 19:56:39 -050059#include "lpfc_debugfs.h"
James Smartb76f2dc2011-07-22 18:37:42 -040060#include "lpfc_bsg.h"
James Smart858c9f62007-06-17 19:56:39 -050061
James Smart923e4b62008-12-04 22:40:07 -050062#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
James Smart3621a712009-04-06 18:47:14 -040063/*
James Smarte59058c2008-08-24 21:49:00 -040064 * debugfs interface
James Smart858c9f62007-06-17 19:56:39 -050065 *
66 * To access this interface the user should:
GeunSik Lim156f5a72009-06-02 15:01:37 +090067 * # mount -t debugfs none /sys/kernel/debug
James Smart858c9f62007-06-17 19:56:39 -050068 *
James Smarte59058c2008-08-24 21:49:00 -040069 * The lpfc debugfs directory hierarchy is:
James Smart2a622bf2011-02-16 12:40:06 -050070 * /sys/kernel/debug/lpfc/fnX/vportY
71 * where X is the lpfc hba function unique_id
James Smart858c9f62007-06-17 19:56:39 -050072 * where Y is the vport VPI on that hba
73 *
74 * Debugging services available per vport:
75 * discovery_trace
76 * This is an ACSII readable file that contains a trace of the last
77 * lpfc_debugfs_max_disc_trc events that happened on a specific vport.
James Smarte59058c2008-08-24 21:49:00 -040078 * See lpfc_debugfs.h for different categories of discovery events.
79 * To enable the discovery trace, the following module parameters must be set:
James Smart858c9f62007-06-17 19:56:39 -050080 * lpfc_debugfs_enable=1 Turns on lpfc debugfs filesystem support
81 * lpfc_debugfs_max_disc_trc=X Where X is the event trace depth for
82 * EACH vport. X MUST also be a power of 2.
83 * lpfc_debugfs_mask_disc_trc=Y Where Y is an event mask as defined in
84 * lpfc_debugfs.h .
James Smarte59058c2008-08-24 21:49:00 -040085 *
86 * slow_ring_trace
87 * This is an ACSII readable file that contains a trace of the last
88 * lpfc_debugfs_max_slow_ring_trc events that happened on a specific HBA.
89 * To enable the slow ring trace, the following module parameters must be set:
90 * lpfc_debugfs_enable=1 Turns on lpfc debugfs filesystem support
91 * lpfc_debugfs_max_slow_ring_trc=X Where X is the event trace depth for
92 * the HBA. X MUST also be a power of 2.
James Smart858c9f62007-06-17 19:56:39 -050093 */
James Smart51ef4c22007-08-02 11:10:31 -040094static int lpfc_debugfs_enable = 1;
James Smartab56dc22011-02-16 12:39:57 -050095module_param(lpfc_debugfs_enable, int, S_IRUGO);
James Smart858c9f62007-06-17 19:56:39 -050096MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services");
97
James Smarta58cbd52007-08-02 11:09:43 -040098/* This MUST be a power of 2 */
James Smartc95d6c62008-01-11 01:53:23 -050099static int lpfc_debugfs_max_disc_trc;
James Smartab56dc22011-02-16 12:39:57 -0500100module_param(lpfc_debugfs_max_disc_trc, int, S_IRUGO);
James Smart858c9f62007-06-17 19:56:39 -0500101MODULE_PARM_DESC(lpfc_debugfs_max_disc_trc,
102 "Set debugfs discovery trace depth");
103
James Smarta58cbd52007-08-02 11:09:43 -0400104/* This MUST be a power of 2 */
James Smartc95d6c62008-01-11 01:53:23 -0500105static int lpfc_debugfs_max_slow_ring_trc;
James Smartab56dc22011-02-16 12:39:57 -0500106module_param(lpfc_debugfs_max_slow_ring_trc, int, S_IRUGO);
James Smarta58cbd52007-08-02 11:09:43 -0400107MODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc,
108 "Set debugfs slow ring trace depth");
109
James Smartbd2cdd52017-02-12 13:52:33 -0800110/* This MUST be a power of 2 */
111static int lpfc_debugfs_max_nvmeio_trc;
112module_param(lpfc_debugfs_max_nvmeio_trc, int, 0444);
113MODULE_PARM_DESC(lpfc_debugfs_max_nvmeio_trc,
114 "Set debugfs NVME IO trace depth");
115
James Smarta257bf92009-04-06 18:48:10 -0400116static int lpfc_debugfs_mask_disc_trc;
James Smartab56dc22011-02-16 12:39:57 -0500117module_param(lpfc_debugfs_mask_disc_trc, int, S_IRUGO);
James Smart858c9f62007-06-17 19:56:39 -0500118MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc,
119 "Set debugfs discovery trace mask");
120
121#include <linux/debugfs.h>
122
James Smart311464e2007-08-02 11:10:37 -0400123static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0);
124static unsigned long lpfc_debugfs_start_time = 0L;
James Smart858c9f62007-06-17 19:56:39 -0500125
James Smart2a622bf2011-02-16 12:40:06 -0500126/* iDiag */
127static struct lpfc_idiag idiag;
128
James Smarte59058c2008-08-24 21:49:00 -0400129/**
James Smart3621a712009-04-06 18:47:14 -0400130 * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer
James Smarte59058c2008-08-24 21:49:00 -0400131 * @vport: The vport to gather the log info from.
132 * @buf: The buffer to dump log into.
133 * @size: The maximum amount of data to process.
134 *
135 * Description:
136 * This routine gathers the lpfc discovery debugfs data from the @vport and
137 * dumps it to @buf up to @size number of bytes. It will start at the next entry
138 * in the log and process the log until the end of the buffer. Then it will
139 * gather from the beginning of the log and process until the current entry.
140 *
141 * Notes:
142 * Discovery logging will be disabled while while this routine dumps the log.
143 *
144 * Return Value:
145 * This routine returns the amount of bytes that were dumped into @buf and will
146 * not exceed @size.
147 **/
James Smart858c9f62007-06-17 19:56:39 -0500148static int
149lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
150{
151 int i, index, len, enable;
152 uint32_t ms;
James Smarta58cbd52007-08-02 11:09:43 -0400153 struct lpfc_debugfs_trc *dtp;
James Smartb76f2dc2011-07-22 18:37:42 -0400154 char *buffer;
155
156 buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL);
157 if (!buffer)
158 return 0;
James Smart858c9f62007-06-17 19:56:39 -0500159
James Smart858c9f62007-06-17 19:56:39 -0500160 enable = lpfc_debugfs_enable;
161 lpfc_debugfs_enable = 0;
162
163 len = 0;
164 index = (atomic_read(&vport->disc_trc_cnt) + 1) &
165 (lpfc_debugfs_max_disc_trc - 1);
166 for (i = index; i < lpfc_debugfs_max_disc_trc; i++) {
167 dtp = vport->disc_trc + i;
168 if (!dtp->fmt)
169 continue;
170 ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
James Smarta58cbd52007-08-02 11:09:43 -0400171 snprintf(buffer,
172 LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
James Smart858c9f62007-06-17 19:56:39 -0500173 dtp->seq_cnt, ms, dtp->fmt);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700174 len += scnprintf(buf+len, size-len, buffer,
James Smart858c9f62007-06-17 19:56:39 -0500175 dtp->data1, dtp->data2, dtp->data3);
176 }
177 for (i = 0; i < index; i++) {
178 dtp = vport->disc_trc + i;
179 if (!dtp->fmt)
180 continue;
181 ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
James Smarta58cbd52007-08-02 11:09:43 -0400182 snprintf(buffer,
183 LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
James Smart858c9f62007-06-17 19:56:39 -0500184 dtp->seq_cnt, ms, dtp->fmt);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700185 len += scnprintf(buf+len, size-len, buffer,
James Smart858c9f62007-06-17 19:56:39 -0500186 dtp->data1, dtp->data2, dtp->data3);
187 }
188
189 lpfc_debugfs_enable = enable;
James Smartb76f2dc2011-07-22 18:37:42 -0400190 kfree(buffer);
191
James Smart858c9f62007-06-17 19:56:39 -0500192 return len;
193}
194
James Smarte59058c2008-08-24 21:49:00 -0400195/**
James Smart3621a712009-04-06 18:47:14 -0400196 * lpfc_debugfs_slow_ring_trc_data - Dump slow ring logging to a buffer
James Smarte59058c2008-08-24 21:49:00 -0400197 * @phba: The HBA to gather the log info from.
198 * @buf: The buffer to dump log into.
199 * @size: The maximum amount of data to process.
200 *
201 * Description:
202 * This routine gathers the lpfc slow ring debugfs data from the @phba and
203 * dumps it to @buf up to @size number of bytes. It will start at the next entry
204 * in the log and process the log until the end of the buffer. Then it will
205 * gather from the beginning of the log and process until the current entry.
206 *
207 * Notes:
208 * Slow ring logging will be disabled while while this routine dumps the log.
209 *
210 * Return Value:
211 * This routine returns the amount of bytes that were dumped into @buf and will
212 * not exceed @size.
213 **/
James Smart858c9f62007-06-17 19:56:39 -0500214static int
James Smarta58cbd52007-08-02 11:09:43 -0400215lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
216{
217 int i, index, len, enable;
218 uint32_t ms;
219 struct lpfc_debugfs_trc *dtp;
James Smartb76f2dc2011-07-22 18:37:42 -0400220 char *buffer;
James Smarta58cbd52007-08-02 11:09:43 -0400221
James Smartb76f2dc2011-07-22 18:37:42 -0400222 buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL);
223 if (!buffer)
224 return 0;
James Smarta58cbd52007-08-02 11:09:43 -0400225
226 enable = lpfc_debugfs_enable;
227 lpfc_debugfs_enable = 0;
228
229 len = 0;
230 index = (atomic_read(&phba->slow_ring_trc_cnt) + 1) &
231 (lpfc_debugfs_max_slow_ring_trc - 1);
232 for (i = index; i < lpfc_debugfs_max_slow_ring_trc; i++) {
233 dtp = phba->slow_ring_trc + i;
234 if (!dtp->fmt)
235 continue;
236 ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
237 snprintf(buffer,
238 LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
239 dtp->seq_cnt, ms, dtp->fmt);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700240 len += scnprintf(buf+len, size-len, buffer,
James Smarta58cbd52007-08-02 11:09:43 -0400241 dtp->data1, dtp->data2, dtp->data3);
242 }
243 for (i = 0; i < index; i++) {
244 dtp = phba->slow_ring_trc + i;
245 if (!dtp->fmt)
246 continue;
247 ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
248 snprintf(buffer,
249 LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
250 dtp->seq_cnt, ms, dtp->fmt);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700251 len += scnprintf(buf+len, size-len, buffer,
James Smarta58cbd52007-08-02 11:09:43 -0400252 dtp->data1, dtp->data2, dtp->data3);
253 }
254
255 lpfc_debugfs_enable = enable;
James Smartb76f2dc2011-07-22 18:37:42 -0400256 kfree(buffer);
257
James Smarta58cbd52007-08-02 11:09:43 -0400258 return len;
259}
260
James Smart311464e2007-08-02 11:10:37 -0400261static int lpfc_debugfs_last_hbq = -1;
James Smart78b2d852007-08-02 11:10:21 -0400262
James Smarte59058c2008-08-24 21:49:00 -0400263/**
James Smart3621a712009-04-06 18:47:14 -0400264 * lpfc_debugfs_hbqinfo_data - Dump host buffer queue info to a buffer
James Smarte59058c2008-08-24 21:49:00 -0400265 * @phba: The HBA to gather host buffer info from.
266 * @buf: The buffer to dump log into.
267 * @size: The maximum amount of data to process.
268 *
269 * Description:
270 * This routine dumps the host buffer queue info from the @phba to @buf up to
271 * @size number of bytes. A header that describes the current hbq state will be
272 * dumped to @buf first and then info on each hbq entry will be dumped to @buf
273 * until @size bytes have been dumped or all the hbq info has been dumped.
274 *
275 * Notes:
276 * This routine will rotate through each configured HBQ each time called.
277 *
278 * Return Value:
279 * This routine returns the amount of bytes that were dumped into @buf and will
280 * not exceed @size.
281 **/
James Smart78b2d852007-08-02 11:10:21 -0400282static int
283lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size)
284{
285 int len = 0;
James Smarteb016562014-09-03 12:58:06 -0400286 int i, j, found, posted, low;
James Smart78b2d852007-08-02 11:10:21 -0400287 uint32_t phys, raw_index, getidx;
288 struct lpfc_hbq_init *hip;
289 struct hbq_s *hbqs;
290 struct lpfc_hbq_entry *hbqe;
291 struct lpfc_dmabuf *d_buf;
292 struct hbq_dmabuf *hbq_buf;
293
James Smart3772a992009-05-22 14:50:54 -0400294 if (phba->sli_rev != 3)
295 return 0;
James Smarteb016562014-09-03 12:58:06 -0400296
James Smart78b2d852007-08-02 11:10:21 -0400297 spin_lock_irq(&phba->hbalock);
298
299 /* toggle between multiple hbqs, if any */
300 i = lpfc_sli_hbq_count();
301 if (i > 1) {
302 lpfc_debugfs_last_hbq++;
303 if (lpfc_debugfs_last_hbq >= i)
304 lpfc_debugfs_last_hbq = 0;
305 }
306 else
307 lpfc_debugfs_last_hbq = 0;
308
309 i = lpfc_debugfs_last_hbq;
310
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700311 len += scnprintf(buf+len, size-len, "HBQ %d Info\n", i);
James Smart78b2d852007-08-02 11:10:21 -0400312
James Smart51ef4c22007-08-02 11:10:31 -0400313 hbqs = &phba->hbqs[i];
James Smart78b2d852007-08-02 11:10:21 -0400314 posted = 0;
James Smart51ef4c22007-08-02 11:10:31 -0400315 list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list)
James Smart78b2d852007-08-02 11:10:21 -0400316 posted++;
317
318 hip = lpfc_hbq_defs[i];
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700319 len += scnprintf(buf+len, size-len,
James Smart78b2d852007-08-02 11:10:21 -0400320 "idx:%d prof:%d rn:%d bufcnt:%d icnt:%d acnt:%d posted %d\n",
321 hip->hbq_index, hip->profile, hip->rn,
322 hip->buffer_count, hip->init_count, hip->add_count, posted);
323
James Smart78b2d852007-08-02 11:10:21 -0400324 raw_index = phba->hbq_get[i];
325 getidx = le32_to_cpu(raw_index);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700326 len += scnprintf(buf+len, size-len,
Colin Ian King1ab62072017-05-26 11:11:37 +0100327 "entries:%d bufcnt:%d Put:%d nPut:%d localGet:%d hbaGet:%d\n",
James Smarta8adb832007-10-27 13:37:53 -0400328 hbqs->entry_count, hbqs->buffer_count, hbqs->hbqPutIdx,
329 hbqs->next_hbqPutIdx, hbqs->local_hbqGetIdx, getidx);
James Smart78b2d852007-08-02 11:10:21 -0400330
James Smart51ef4c22007-08-02 11:10:31 -0400331 hbqe = (struct lpfc_hbq_entry *) phba->hbqs[i].hbq_virt;
James Smart78b2d852007-08-02 11:10:21 -0400332 for (j=0; j<hbqs->entry_count; j++) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700333 len += scnprintf(buf+len, size-len,
James Smart78b2d852007-08-02 11:10:21 -0400334 "%03d: %08x %04x %05x ", j,
James Smarta8adb832007-10-27 13:37:53 -0400335 le32_to_cpu(hbqe->bde.addrLow),
336 le32_to_cpu(hbqe->bde.tus.w),
337 le32_to_cpu(hbqe->buffer_tag));
James Smart78b2d852007-08-02 11:10:21 -0400338 i = 0;
339 found = 0;
340
341 /* First calculate if slot has an associated posted buffer */
342 low = hbqs->hbqPutIdx - posted;
343 if (low >= 0) {
344 if ((j >= hbqs->hbqPutIdx) || (j < low)) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700345 len += scnprintf(buf + len, size - len,
346 "Unused\n");
James Smart78b2d852007-08-02 11:10:21 -0400347 goto skipit;
348 }
349 }
350 else {
351 if ((j >= hbqs->hbqPutIdx) &&
352 (j < (hbqs->entry_count+low))) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700353 len += scnprintf(buf + len, size - len,
354 "Unused\n");
James Smart78b2d852007-08-02 11:10:21 -0400355 goto skipit;
356 }
357 }
358
359 /* Get the Buffer info for the posted buffer */
James Smart51ef4c22007-08-02 11:10:31 -0400360 list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list) {
James Smart78b2d852007-08-02 11:10:21 -0400361 hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf);
362 phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff);
James Smarta8adb832007-10-27 13:37:53 -0400363 if (phys == le32_to_cpu(hbqe->bde.addrLow)) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700364 len += scnprintf(buf+len, size-len,
James Smart32350662019-08-14 16:57:06 -0700365 "Buf%d: x%px %06x\n", i,
James Smart78b2d852007-08-02 11:10:21 -0400366 hbq_buf->dbuf.virt, hbq_buf->tag);
367 found = 1;
368 break;
369 }
370 i++;
371 }
372 if (!found) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700373 len += scnprintf(buf+len, size-len, "No DMAinfo?\n");
James Smart78b2d852007-08-02 11:10:21 -0400374 }
375skipit:
376 hbqe++;
377 if (len > LPFC_HBQINFO_SIZE - 54)
378 break;
379 }
380 spin_unlock_irq(&phba->hbalock);
381 return len;
382}
383
James Smart6a828b02019-01-28 11:14:31 -0800384static int lpfc_debugfs_last_xripool;
385
386/**
387 * lpfc_debugfs_common_xri_data - Dump Hardware Queue info to a buffer
388 * @phba: The HBA to gather host buffer info from.
389 * @buf: The buffer to dump log into.
390 * @size: The maximum amount of data to process.
391 *
392 * Description:
393 * This routine dumps the Hardware Queue info from the @phba to @buf up to
394 * @size number of bytes. A header that describes the current hdwq state will be
395 * dumped to @buf first and then info on each hdwq entry will be dumped to @buf
396 * until @size bytes have been dumped or all the hdwq info has been dumped.
397 *
398 * Notes:
399 * This routine will rotate through each configured Hardware Queue each
400 * time called.
401 *
402 * Return Value:
403 * This routine returns the amount of bytes that were dumped into @buf and will
404 * not exceed @size.
405 **/
406static int
407lpfc_debugfs_commonxripools_data(struct lpfc_hba *phba, char *buf, int size)
408{
409 struct lpfc_sli4_hdw_queue *qp;
410 int len = 0;
411 int i, out;
412 unsigned long iflag;
413
414 for (i = 0; i < phba->cfg_hdw_queue; i++) {
415 if (len > (LPFC_DUMP_MULTIXRIPOOL_SIZE - 80))
416 break;
417 qp = &phba->sli4_hba.hdwq[lpfc_debugfs_last_xripool];
418
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700419 len += scnprintf(buf + len, size - len, "HdwQ %d Info ", i);
James Smartc00f62e2019-08-14 16:57:11 -0700420 spin_lock_irqsave(&qp->abts_io_buf_list_lock, iflag);
James Smart6a828b02019-01-28 11:14:31 -0800421 spin_lock(&qp->io_buf_list_get_lock);
422 spin_lock(&qp->io_buf_list_put_lock);
423 out = qp->total_io_bufs - (qp->get_io_bufs + qp->put_io_bufs +
424 qp->abts_scsi_io_bufs + qp->abts_nvme_io_bufs);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700425 len += scnprintf(buf + len, size - len,
James Smart6a828b02019-01-28 11:14:31 -0800426 "tot:%d get:%d put:%d mt:%d "
427 "ABTS scsi:%d nvme:%d Out:%d\n",
428 qp->total_io_bufs, qp->get_io_bufs, qp->put_io_bufs,
429 qp->empty_io_bufs, qp->abts_scsi_io_bufs,
430 qp->abts_nvme_io_bufs, out);
431 spin_unlock(&qp->io_buf_list_put_lock);
432 spin_unlock(&qp->io_buf_list_get_lock);
James Smartc00f62e2019-08-14 16:57:11 -0700433 spin_unlock_irqrestore(&qp->abts_io_buf_list_lock, iflag);
James Smart6a828b02019-01-28 11:14:31 -0800434
435 lpfc_debugfs_last_xripool++;
436 if (lpfc_debugfs_last_xripool >= phba->cfg_hdw_queue)
437 lpfc_debugfs_last_xripool = 0;
438 }
439
440 return len;
441}
442
James Smartc4908502019-01-28 11:14:28 -0800443/**
444 * lpfc_debugfs_multixripools_data - Display multi-XRI pools information
445 * @phba: The HBA to gather host buffer info from.
446 * @buf: The buffer to dump log into.
447 * @size: The maximum amount of data to process.
448 *
449 * Description:
450 * This routine displays current multi-XRI pools information including XRI
451 * count in public, private and txcmplq. It also displays current high and
452 * low watermark.
453 *
454 * Return Value:
455 * This routine returns the amount of bytes that were dumped into @buf and will
456 * not exceed @size.
457 **/
458static int
459lpfc_debugfs_multixripools_data(struct lpfc_hba *phba, char *buf, int size)
460{
461 u32 i;
462 u32 hwq_count;
463 struct lpfc_sli4_hdw_queue *qp;
464 struct lpfc_multixri_pool *multixri_pool;
465 struct lpfc_pvt_pool *pvt_pool;
466 struct lpfc_pbl_pool *pbl_pool;
467 u32 txcmplq_cnt;
468 char tmp[LPFC_DEBUG_OUT_LINE_SZ] = {0};
469
James Smart6a828b02019-01-28 11:14:31 -0800470 if (phba->sli_rev != LPFC_SLI_REV4)
471 return 0;
472
473 if (!phba->sli4_hba.hdwq)
474 return 0;
475
476 if (!phba->cfg_xri_rebalancing) {
477 i = lpfc_debugfs_commonxripools_data(phba, buf, size);
478 return i;
479 }
480
James Smartc4908502019-01-28 11:14:28 -0800481 /*
482 * Pbl: Current number of free XRIs in public pool
483 * Pvt: Current number of free XRIs in private pool
484 * Busy: Current number of outstanding XRIs
485 * HWM: Current high watermark
486 * pvt_empty: Incremented by 1 when IO submission fails (no xri)
487 * pbl_empty: Incremented by 1 when all pbl_pool are empty during
488 * IO submission
489 */
490 scnprintf(tmp, sizeof(tmp),
491 "HWQ: Pbl Pvt Busy HWM | pvt_empty pbl_empty ");
492 if (strlcat(buf, tmp, size) >= size)
493 return strnlen(buf, size);
494
495#ifdef LPFC_MXP_STAT
496 /*
497 * MAXH: Max high watermark seen so far
498 * above_lmt: Incremented by 1 if xri_owned > xri_limit during
499 * IO submission
500 * below_lmt: Incremented by 1 if xri_owned <= xri_limit during
501 * IO submission
502 * locPbl_hit: Incremented by 1 if successfully get a batch of XRI from
503 * local pbl_pool
504 * othPbl_hit: Incremented by 1 if successfully get a batch of XRI from
505 * other pbl_pool
506 */
507 scnprintf(tmp, sizeof(tmp),
508 "MAXH above_lmt below_lmt locPbl_hit othPbl_hit");
509 if (strlcat(buf, tmp, size) >= size)
510 return strnlen(buf, size);
511
512 /*
513 * sPbl: snapshot of Pbl 15 sec after stat gets cleared
514 * sPvt: snapshot of Pvt 15 sec after stat gets cleared
515 * sBusy: snapshot of Busy 15 sec after stat gets cleared
516 */
517 scnprintf(tmp, sizeof(tmp),
518 " | sPbl sPvt sBusy");
519 if (strlcat(buf, tmp, size) >= size)
520 return strnlen(buf, size);
521#endif
522
523 scnprintf(tmp, sizeof(tmp), "\n");
524 if (strlcat(buf, tmp, size) >= size)
525 return strnlen(buf, size);
526
527 hwq_count = phba->cfg_hdw_queue;
528 for (i = 0; i < hwq_count; i++) {
529 qp = &phba->sli4_hba.hdwq[i];
530 multixri_pool = qp->p_multixri_pool;
531 if (!multixri_pool)
532 continue;
533 pbl_pool = &multixri_pool->pbl_pool;
534 pvt_pool = &multixri_pool->pvt_pool;
James Smartc00f62e2019-08-14 16:57:11 -0700535 txcmplq_cnt = qp->io_wq->pring->txcmplq_cnt;
James Smartc4908502019-01-28 11:14:28 -0800536
537 scnprintf(tmp, sizeof(tmp),
538 "%03d: %4d %4d %4d %4d | %10d %10d ",
539 i, pbl_pool->count, pvt_pool->count,
540 txcmplq_cnt, pvt_pool->high_watermark,
541 qp->empty_io_bufs, multixri_pool->pbl_empty_count);
542 if (strlcat(buf, tmp, size) >= size)
543 break;
544
545#ifdef LPFC_MXP_STAT
546 scnprintf(tmp, sizeof(tmp),
547 "%4d %10d %10d %10d %10d",
548 multixri_pool->stat_max_hwm,
549 multixri_pool->above_limit_count,
550 multixri_pool->below_limit_count,
551 multixri_pool->local_pbl_hit_count,
552 multixri_pool->other_pbl_hit_count);
553 if (strlcat(buf, tmp, size) >= size)
554 break;
555
556 scnprintf(tmp, sizeof(tmp),
557 " | %4d %4d %5d",
558 multixri_pool->stat_pbl_count,
559 multixri_pool->stat_pvt_count,
560 multixri_pool->stat_busy_count);
561 if (strlcat(buf, tmp, size) >= size)
562 break;
563#endif
564
565 scnprintf(tmp, sizeof(tmp), "\n");
566 if (strlcat(buf, tmp, size) >= size)
567 break;
568 }
569 return strnlen(buf, size);
570}
571
James Smart6a828b02019-01-28 11:14:31 -0800572
573#ifdef LPFC_HDWQ_LOCK_STAT
574static int lpfc_debugfs_last_lock;
James Smart5e5b5112019-01-28 11:14:22 -0800575
576/**
James Smart6a828b02019-01-28 11:14:31 -0800577 * lpfc_debugfs_lockstat_data - Dump Hardware Queue info to a buffer
James Smart5e5b5112019-01-28 11:14:22 -0800578 * @phba: The HBA to gather host buffer info from.
579 * @buf: The buffer to dump log into.
580 * @size: The maximum amount of data to process.
581 *
582 * Description:
583 * This routine dumps the Hardware Queue info from the @phba to @buf up to
584 * @size number of bytes. A header that describes the current hdwq state will be
585 * dumped to @buf first and then info on each hdwq entry will be dumped to @buf
586 * until @size bytes have been dumped or all the hdwq info has been dumped.
587 *
588 * Notes:
589 * This routine will rotate through each configured Hardware Queue each
590 * time called.
591 *
592 * Return Value:
593 * This routine returns the amount of bytes that were dumped into @buf and will
594 * not exceed @size.
595 **/
596static int
James Smart6a828b02019-01-28 11:14:31 -0800597lpfc_debugfs_lockstat_data(struct lpfc_hba *phba, char *buf, int size)
James Smart5e5b5112019-01-28 11:14:22 -0800598{
599 struct lpfc_sli4_hdw_queue *qp;
600 int len = 0;
James Smart6a828b02019-01-28 11:14:31 -0800601 int i;
James Smart5e5b5112019-01-28 11:14:22 -0800602
603 if (phba->sli_rev != LPFC_SLI_REV4)
604 return 0;
605
606 if (!phba->sli4_hba.hdwq)
607 return 0;
608
609 for (i = 0; i < phba->cfg_hdw_queue; i++) {
James Smart6a828b02019-01-28 11:14:31 -0800610 if (len > (LPFC_HDWQINFO_SIZE - 100))
James Smart5e5b5112019-01-28 11:14:22 -0800611 break;
James Smart6a828b02019-01-28 11:14:31 -0800612 qp = &phba->sli4_hba.hdwq[lpfc_debugfs_last_lock];
James Smart5e5b5112019-01-28 11:14:22 -0800613
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700614 len += scnprintf(buf + len, size - len, "HdwQ %03d Lock ", i);
James Smart6a828b02019-01-28 11:14:31 -0800615 if (phba->cfg_xri_rebalancing) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700616 len += scnprintf(buf + len, size - len,
James Smart6a828b02019-01-28 11:14:31 -0800617 "get_pvt:%d mv_pvt:%d "
618 "mv2pub:%d mv2pvt:%d "
619 "put_pvt:%d put_pub:%d wq:%d\n",
620 qp->lock_conflict.alloc_pvt_pool,
621 qp->lock_conflict.mv_from_pvt_pool,
622 qp->lock_conflict.mv_to_pub_pool,
623 qp->lock_conflict.mv_to_pvt_pool,
624 qp->lock_conflict.free_pvt_pool,
625 qp->lock_conflict.free_pub_pool,
626 qp->lock_conflict.wq_access);
627 } else {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700628 len += scnprintf(buf + len, size - len,
James Smart6a828b02019-01-28 11:14:31 -0800629 "get:%d put:%d free:%d wq:%d\n",
630 qp->lock_conflict.alloc_xri_get,
631 qp->lock_conflict.alloc_xri_put,
632 qp->lock_conflict.free_xri,
633 qp->lock_conflict.wq_access);
634 }
James Smart5e5b5112019-01-28 11:14:22 -0800635
James Smart6a828b02019-01-28 11:14:31 -0800636 lpfc_debugfs_last_lock++;
637 if (lpfc_debugfs_last_lock >= phba->cfg_hdw_queue)
638 lpfc_debugfs_last_lock = 0;
James Smart5e5b5112019-01-28 11:14:22 -0800639 }
640
641 return len;
642}
James Smart6a828b02019-01-28 11:14:31 -0800643#endif
James Smart5e5b5112019-01-28 11:14:22 -0800644
James Smartc95d6c62008-01-11 01:53:23 -0500645static int lpfc_debugfs_last_hba_slim_off;
646
James Smarte59058c2008-08-24 21:49:00 -0400647/**
James Smart3621a712009-04-06 18:47:14 -0400648 * lpfc_debugfs_dumpHBASlim_data - Dump HBA SLIM info to a buffer
James Smarte59058c2008-08-24 21:49:00 -0400649 * @phba: The HBA to gather SLIM info from.
650 * @buf: The buffer to dump log into.
651 * @size: The maximum amount of data to process.
652 *
653 * Description:
654 * This routine dumps the current contents of HBA SLIM for the HBA associated
655 * with @phba to @buf up to @size bytes of data. This is the raw HBA SLIM data.
656 *
657 * Notes:
658 * This routine will only dump up to 1024 bytes of data each time called and
659 * should be called multiple times to dump the entire HBA SLIM.
660 *
661 * Return Value:
662 * This routine returns the amount of bytes that were dumped into @buf and will
663 * not exceed @size.
664 **/
James Smarta58cbd52007-08-02 11:09:43 -0400665static int
James Smartc95d6c62008-01-11 01:53:23 -0500666lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
James Smarta58cbd52007-08-02 11:09:43 -0400667{
668 int len = 0;
James Smartc95d6c62008-01-11 01:53:23 -0500669 int i, off;
670 uint32_t *ptr;
James Smartb76f2dc2011-07-22 18:37:42 -0400671 char *buffer;
672
673 buffer = kmalloc(1024, GFP_KERNEL);
674 if (!buffer)
675 return 0;
James Smartc95d6c62008-01-11 01:53:23 -0500676
677 off = 0;
678 spin_lock_irq(&phba->hbalock);
679
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700680 len += scnprintf(buf+len, size-len, "HBA SLIM\n");
James Smartc95d6c62008-01-11 01:53:23 -0500681 lpfc_memcpy_from_slim(buffer,
James Smarta257bf92009-04-06 18:48:10 -0400682 phba->MBslimaddr + lpfc_debugfs_last_hba_slim_off, 1024);
James Smartc95d6c62008-01-11 01:53:23 -0500683
684 ptr = (uint32_t *)&buffer[0];
685 off = lpfc_debugfs_last_hba_slim_off;
686
687 /* Set it up for the next time */
688 lpfc_debugfs_last_hba_slim_off += 1024;
689 if (lpfc_debugfs_last_hba_slim_off >= 4096)
690 lpfc_debugfs_last_hba_slim_off = 0;
691
692 i = 1024;
693 while (i > 0) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700694 len += scnprintf(buf+len, size-len,
James Smartc95d6c62008-01-11 01:53:23 -0500695 "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
696 off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4),
697 *(ptr+5), *(ptr+6), *(ptr+7));
698 ptr += 8;
699 i -= (8 * sizeof(uint32_t));
700 off += (8 * sizeof(uint32_t));
701 }
702
703 spin_unlock_irq(&phba->hbalock);
James Smartb76f2dc2011-07-22 18:37:42 -0400704 kfree(buffer);
705
James Smartc95d6c62008-01-11 01:53:23 -0500706 return len;
707}
708
James Smarte59058c2008-08-24 21:49:00 -0400709/**
James Smart3621a712009-04-06 18:47:14 -0400710 * lpfc_debugfs_dumpHostSlim_data - Dump host SLIM info to a buffer
James Smarte59058c2008-08-24 21:49:00 -0400711 * @phba: The HBA to gather Host SLIM info from.
712 * @buf: The buffer to dump log into.
713 * @size: The maximum amount of data to process.
714 *
715 * Description:
716 * This routine dumps the current contents of host SLIM for the host associated
717 * with @phba to @buf up to @size bytes of data. The dump will contain the
718 * Mailbox, PCB, Rings, and Registers that are located in host memory.
719 *
720 * Return Value:
721 * This routine returns the amount of bytes that were dumped into @buf and will
722 * not exceed @size.
723 **/
James Smartc95d6c62008-01-11 01:53:23 -0500724static int
725lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size)
726{
727 int len = 0;
728 int i, off;
James Smarta58cbd52007-08-02 11:09:43 -0400729 uint32_t word0, word1, word2, word3;
730 uint32_t *ptr;
731 struct lpfc_pgp *pgpp;
732 struct lpfc_sli *psli = &phba->sli;
733 struct lpfc_sli_ring *pring;
734
James Smarta58cbd52007-08-02 11:09:43 -0400735 off = 0;
736 spin_lock_irq(&phba->hbalock);
737
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700738 len += scnprintf(buf+len, size-len, "SLIM Mailbox\n");
James Smart34b02dc2008-08-24 21:49:55 -0400739 ptr = (uint32_t *)phba->slim2p.virt;
James Smarta58cbd52007-08-02 11:09:43 -0400740 i = sizeof(MAILBOX_t);
741 while (i > 0) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700742 len += scnprintf(buf+len, size-len,
James Smarta58cbd52007-08-02 11:09:43 -0400743 "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
744 off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4),
745 *(ptr+5), *(ptr+6), *(ptr+7));
746 ptr += 8;
747 i -= (8 * sizeof(uint32_t));
748 off += (8 * sizeof(uint32_t));
749 }
750
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700751 len += scnprintf(buf+len, size-len, "SLIM PCB\n");
James Smart34b02dc2008-08-24 21:49:55 -0400752 ptr = (uint32_t *)phba->pcb;
James Smarta58cbd52007-08-02 11:09:43 -0400753 i = sizeof(PCB_t);
754 while (i > 0) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700755 len += scnprintf(buf+len, size-len,
James Smarta58cbd52007-08-02 11:09:43 -0400756 "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
757 off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4),
758 *(ptr+5), *(ptr+6), *(ptr+7));
759 ptr += 8;
760 i -= (8 * sizeof(uint32_t));
761 off += (8 * sizeof(uint32_t));
762 }
763
James Smart3772a992009-05-22 14:50:54 -0400764 if (phba->sli_rev <= LPFC_SLI_REV3) {
James Smart895427b2017-02-12 13:52:30 -0800765 for (i = 0; i < 4; i++) {
766 pgpp = &phba->port_gp[i];
767 pring = &psli->sli3_ring[i];
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700768 len += scnprintf(buf+len, size-len,
James Smart895427b2017-02-12 13:52:30 -0800769 "Ring %d: CMD GetInx:%d "
770 "(Max:%d Next:%d "
771 "Local:%d flg:x%x) "
772 "RSP PutInx:%d Max:%d\n",
773 i, pgpp->cmdGetInx,
774 pring->sli.sli3.numCiocb,
775 pring->sli.sli3.next_cmdidx,
776 pring->sli.sli3.local_getidx,
777 pring->flag, pgpp->rspPutInx,
778 pring->sli.sli3.numRiocb);
779 }
780
James Smart3772a992009-05-22 14:50:54 -0400781 word0 = readl(phba->HAregaddr);
782 word1 = readl(phba->CAregaddr);
783 word2 = readl(phba->HSregaddr);
784 word3 = readl(phba->HCregaddr);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700785 len += scnprintf(buf+len, size-len, "HA:%08x CA:%08x HS:%08x "
James Smart3772a992009-05-22 14:50:54 -0400786 "HC:%08x\n", word0, word1, word2, word3);
787 }
James Smarta58cbd52007-08-02 11:09:43 -0400788 spin_unlock_irq(&phba->hbalock);
789 return len;
790}
791
James Smarte59058c2008-08-24 21:49:00 -0400792/**
James Smart3621a712009-04-06 18:47:14 -0400793 * lpfc_debugfs_nodelist_data - Dump target node list to a buffer
James Smarte59058c2008-08-24 21:49:00 -0400794 * @vport: The vport to gather target node info from.
795 * @buf: The buffer to dump log into.
796 * @size: The maximum amount of data to process.
797 *
798 * Description:
799 * This routine dumps the current target node list associated with @vport to
800 * @buf up to @size bytes of data. Each node entry in the dump will contain a
801 * node state, DID, WWPN, WWNN, RPI, flags, type, and other useful fields.
802 *
803 * Return Value:
804 * This routine returns the amount of bytes that were dumped into @buf and will
805 * not exceed @size.
806 **/
James Smarta58cbd52007-08-02 11:09:43 -0400807static int
James Smart858c9f62007-06-17 19:56:39 -0500808lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
809{
810 int len = 0;
James Smartf91bc592018-04-09 14:24:22 -0700811 int i, iocnt, outio, cnt;
James Smart858c9f62007-06-17 19:56:39 -0500812 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smart2b65e182017-02-12 13:52:38 -0800813 struct lpfc_hba *phba = vport->phba;
James Smart858c9f62007-06-17 19:56:39 -0500814 struct lpfc_nodelist *ndlp;
James Smart2ea259e2017-02-12 13:52:27 -0800815 unsigned char *statep;
James Smartbd2cdd52017-02-12 13:52:33 -0800816 struct nvme_fc_local_port *localport;
James Smart9e210172018-09-13 15:41:10 -0700817 struct nvme_fc_remote_port *nrport = NULL;
James Smart01466022018-04-09 14:24:27 -0700818 struct lpfc_nvme_rport *rport;
James Smart858c9f62007-06-17 19:56:39 -0500819
820 cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
James Smartf91bc592018-04-09 14:24:22 -0700821 outio = 0;
James Smart858c9f62007-06-17 19:56:39 -0500822
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700823 len += scnprintf(buf+len, size-len, "\nFCP Nodelist Entries ...\n");
James Smart858c9f62007-06-17 19:56:39 -0500824 spin_lock_irq(shost->host_lock);
825 list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
James Smartf91bc592018-04-09 14:24:22 -0700826 iocnt = 0;
James Smart858c9f62007-06-17 19:56:39 -0500827 if (!cnt) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700828 len += scnprintf(buf+len, size-len,
James Smart858c9f62007-06-17 19:56:39 -0500829 "Missing Nodelist Entries\n");
830 break;
831 }
832 cnt--;
833 switch (ndlp->nlp_state) {
834 case NLP_STE_UNUSED_NODE:
835 statep = "UNUSED";
836 break;
837 case NLP_STE_PLOGI_ISSUE:
838 statep = "PLOGI ";
839 break;
840 case NLP_STE_ADISC_ISSUE:
841 statep = "ADISC ";
842 break;
843 case NLP_STE_REG_LOGIN_ISSUE:
844 statep = "REGLOG";
845 break;
846 case NLP_STE_PRLI_ISSUE:
847 statep = "PRLI ";
848 break;
James Smart086a3452012-08-14 14:25:21 -0400849 case NLP_STE_LOGO_ISSUE:
850 statep = "LOGO ";
851 break;
James Smart858c9f62007-06-17 19:56:39 -0500852 case NLP_STE_UNMAPPED_NODE:
853 statep = "UNMAP ";
James Smartf91bc592018-04-09 14:24:22 -0700854 iocnt = 1;
James Smart858c9f62007-06-17 19:56:39 -0500855 break;
856 case NLP_STE_MAPPED_NODE:
857 statep = "MAPPED";
James Smartf91bc592018-04-09 14:24:22 -0700858 iocnt = 1;
James Smart858c9f62007-06-17 19:56:39 -0500859 break;
860 case NLP_STE_NPR_NODE:
861 statep = "NPR ";
862 break;
863 default:
864 statep = "UNKNOWN";
865 }
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700866 len += scnprintf(buf+len, size-len, "%s DID:x%06x ",
James Smart2ea259e2017-02-12 13:52:27 -0800867 statep, ndlp->nlp_DID);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700868 len += scnprintf(buf+len, size-len,
James Smart2ea259e2017-02-12 13:52:27 -0800869 "WWPN x%llx ",
870 wwn_to_u64(ndlp->nlp_portname.u.wwn));
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700871 len += scnprintf(buf+len, size-len,
James Smart2ea259e2017-02-12 13:52:27 -0800872 "WWNN x%llx ",
873 wwn_to_u64(ndlp->nlp_nodename.u.wwn));
James Smart086a3452012-08-14 14:25:21 -0400874 if (ndlp->nlp_flag & NLP_RPI_REGISTERED)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700875 len += scnprintf(buf+len, size-len, "RPI:%03d ",
James Smart2ea259e2017-02-12 13:52:27 -0800876 ndlp->nlp_rpi);
James Smart086a3452012-08-14 14:25:21 -0400877 else
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700878 len += scnprintf(buf+len, size-len, "RPI:none ");
879 len += scnprintf(buf+len, size-len, "flag:x%08x ",
James Smart086a3452012-08-14 14:25:21 -0400880 ndlp->nlp_flag);
James Smart858c9f62007-06-17 19:56:39 -0500881 if (!ndlp->nlp_type)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700882 len += scnprintf(buf+len, size-len, "UNKNOWN_TYPE ");
James Smart858c9f62007-06-17 19:56:39 -0500883 if (ndlp->nlp_type & NLP_FC_NODE)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700884 len += scnprintf(buf+len, size-len, "FC_NODE ");
James Smartf91bc592018-04-09 14:24:22 -0700885 if (ndlp->nlp_type & NLP_FABRIC) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700886 len += scnprintf(buf+len, size-len, "FABRIC ");
James Smartf91bc592018-04-09 14:24:22 -0700887 iocnt = 0;
888 }
James Smart858c9f62007-06-17 19:56:39 -0500889 if (ndlp->nlp_type & NLP_FCP_TARGET)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700890 len += scnprintf(buf+len, size-len, "FCP_TGT sid:%d ",
James Smart858c9f62007-06-17 19:56:39 -0500891 ndlp->nlp_sid);
892 if (ndlp->nlp_type & NLP_FCP_INITIATOR)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700893 len += scnprintf(buf+len, size-len, "FCP_INITIATOR ");
James Smart7d790f02017-06-01 21:06:57 -0700894 if (ndlp->nlp_type & NLP_NVME_TARGET)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700895 len += scnprintf(buf + len,
James Smart7d790f02017-06-01 21:06:57 -0700896 size - len, "NVME_TGT sid:%d ",
897 NLP_NO_SID);
898 if (ndlp->nlp_type & NLP_NVME_INITIATOR)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700899 len += scnprintf(buf + len,
James Smart7d790f02017-06-01 21:06:57 -0700900 size - len, "NVME_INITIATOR ");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700901 len += scnprintf(buf+len, size-len, "usgmap:%x ",
James Smart58da1ff2008-04-07 10:15:56 -0400902 ndlp->nlp_usg_map);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700903 len += scnprintf(buf+len, size-len, "refcnt:%x",
Peter Zijlstra2c935bc2016-11-14 17:29:48 +0100904 kref_read(&ndlp->kref));
James Smartf91bc592018-04-09 14:24:22 -0700905 if (iocnt) {
906 i = atomic_read(&ndlp->cmd_pending);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700907 len += scnprintf(buf + len, size - len,
James Smartf91bc592018-04-09 14:24:22 -0700908 " OutIO:x%x Qdepth x%x",
909 i, ndlp->cmd_qdepth);
910 outio += i;
911 }
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700912 len += scnprintf(buf + len, size - len, "defer:%x ",
James Smartdea16bd2018-11-29 16:09:30 -0800913 ndlp->nlp_defer_did);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700914 len += scnprintf(buf+len, size-len, "\n");
James Smart858c9f62007-06-17 19:56:39 -0500915 }
916 spin_unlock_irq(shost->host_lock);
James Smart2ea259e2017-02-12 13:52:27 -0800917
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700918 len += scnprintf(buf + len, size - len,
James Smartf91bc592018-04-09 14:24:22 -0700919 "\nOutstanding IO x%x\n", outio);
920
James Smart2b65e182017-02-12 13:52:38 -0800921 if (phba->nvmet_support && phba->targetport && (vport == phba->pport)) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700922 len += scnprintf(buf + len, size - len,
James Smart2b65e182017-02-12 13:52:38 -0800923 "\nNVME Targetport Entry ...\n");
924
925 /* Port state is only one of two values for now. */
926 if (phba->targetport->port_id)
927 statep = "REGISTERED";
928 else
929 statep = "INIT";
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700930 len += scnprintf(buf + len, size - len,
James Smart2b65e182017-02-12 13:52:38 -0800931 "TGT WWNN x%llx WWPN x%llx State %s\n",
932 wwn_to_u64(vport->fc_nodename.u.wwn),
933 wwn_to_u64(vport->fc_portname.u.wwn),
934 statep);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700935 len += scnprintf(buf + len, size - len,
James Smart2b65e182017-02-12 13:52:38 -0800936 " Targetport DID x%06x\n",
937 phba->targetport->port_id);
938 goto out_exit;
939 }
940
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700941 len += scnprintf(buf + len, size - len,
James Smartbd2cdd52017-02-12 13:52:33 -0800942 "\nNVME Lport/Rport Entries ...\n");
943
944 localport = vport->localport;
945 if (!localport)
946 goto out_exit;
947
948 spin_lock_irq(shost->host_lock);
James Smartbd2cdd52017-02-12 13:52:33 -0800949
950 /* Port state is only one of two values for now. */
951 if (localport->port_id)
952 statep = "ONLINE";
953 else
954 statep = "UNKNOWN ";
955
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700956 len += scnprintf(buf + len, size - len,
James Smartbd2cdd52017-02-12 13:52:33 -0800957 "Lport DID x%06x PortState %s\n",
958 localport->port_id, statep);
959
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700960 len += scnprintf(buf + len, size - len, "\tRport List:\n");
James Smart80cc0042017-06-01 21:06:56 -0700961 list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
James Smartbd2cdd52017-02-12 13:52:33 -0800962 /* local short-hand pointer. */
James Smart9e210172018-09-13 15:41:10 -0700963 spin_lock(&phba->hbalock);
James Smart01466022018-04-09 14:24:27 -0700964 rport = lpfc_ndlp_get_nrport(ndlp);
James Smart9e210172018-09-13 15:41:10 -0700965 if (rport)
966 nrport = rport->remoteport;
Arnd Bergmannf8d29432018-11-02 16:35:48 +0100967 else
968 nrport = NULL;
James Smart9e210172018-09-13 15:41:10 -0700969 spin_unlock(&phba->hbalock);
James Smart01466022018-04-09 14:24:27 -0700970 if (!nrport)
971 continue;
James Smartbd2cdd52017-02-12 13:52:33 -0800972
973 /* Port state is only one of two values for now. */
974 switch (nrport->port_state) {
975 case FC_OBJSTATE_ONLINE:
976 statep = "ONLINE";
977 break;
978 case FC_OBJSTATE_UNKNOWN:
979 statep = "UNKNOWN ";
980 break;
981 default:
982 statep = "UNSUPPORTED";
983 break;
984 }
985
986 /* Tab in to show lport ownership. */
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700987 len += scnprintf(buf + len, size - len,
James Smartbd2cdd52017-02-12 13:52:33 -0800988 "\t%s Port ID:x%06x ",
989 statep, nrport->port_id);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700990 len += scnprintf(buf + len, size - len, "WWPN x%llx ",
James Smartbd2cdd52017-02-12 13:52:33 -0800991 nrport->port_name);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700992 len += scnprintf(buf + len, size - len, "WWNN x%llx ",
James Smartbd2cdd52017-02-12 13:52:33 -0800993 nrport->node_name);
James Smart7d790f02017-06-01 21:06:57 -0700994
995 /* An NVME rport can have multiple roles. */
996 if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -0700997 len += scnprintf(buf + len, size - len,
James Smart7d790f02017-06-01 21:06:57 -0700998 "INITIATOR ");
999 if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001000 len += scnprintf(buf + len, size - len,
James Smart7d790f02017-06-01 21:06:57 -07001001 "TARGET ");
1002 if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001003 len += scnprintf(buf + len, size - len,
James Smart7d790f02017-06-01 21:06:57 -07001004 "DISCSRVC ");
1005 if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR |
1006 FC_PORT_ROLE_NVME_TARGET |
1007 FC_PORT_ROLE_NVME_DISCOVERY))
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001008 len += scnprintf(buf + len, size - len,
James Smartbd2cdd52017-02-12 13:52:33 -08001009 "UNKNOWN ROLE x%x",
1010 nrport->port_role);
James Smartbd2cdd52017-02-12 13:52:33 -08001011 /* Terminate the string. */
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001012 len += scnprintf(buf + len, size - len, "\n");
James Smartbd2cdd52017-02-12 13:52:33 -08001013 }
1014
1015 spin_unlock_irq(shost->host_lock);
1016 out_exit:
1017 return len;
1018}
1019
1020/**
1021 * lpfc_debugfs_nvmestat_data - Dump target node list to a buffer
1022 * @vport: The vport to gather target node info from.
1023 * @buf: The buffer to dump log into.
1024 * @size: The maximum amount of data to process.
1025 *
1026 * Description:
1027 * This routine dumps the NVME statistics associated with @vport
1028 *
1029 * Return Value:
1030 * This routine returns the amount of bytes that were dumped into @buf and will
1031 * not exceed @size.
1032 **/
1033static int
1034lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size)
1035{
1036 struct lpfc_hba *phba = vport->phba;
James Smart2b65e182017-02-12 13:52:38 -08001037 struct lpfc_nvmet_tgtport *tgtp;
James Smart86c67372017-04-21 16:05:04 -07001038 struct lpfc_nvmet_rcv_ctx *ctxp, *next_ctxp;
James Smart4b056682017-12-08 17:18:10 -08001039 struct nvme_fc_local_port *localport;
James Smart4c47efc2019-01-28 11:14:25 -08001040 struct lpfc_fc4_ctrl_stat *cstat;
James Smart4b056682017-12-08 17:18:10 -08001041 struct lpfc_nvme_lport *lport;
James Smart66a210f2018-04-09 14:24:23 -07001042 uint64_t data1, data2, data3;
1043 uint64_t tot, totin, totout;
James Smart6a828b02019-01-28 11:14:31 -08001044 int cnt, i;
James Smartbd2cdd52017-02-12 13:52:33 -08001045 int len = 0;
1046
James Smart2b65e182017-02-12 13:52:38 -08001047 if (phba->nvmet_support) {
1048 if (!phba->targetport)
1049 return len;
1050 tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001051 len += scnprintf(buf + len, size - len,
James Smart2b65e182017-02-12 13:52:38 -08001052 "\nNVME Targetport Statistics\n");
1053
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001054 len += scnprintf(buf + len, size - len,
James Smart2b65e182017-02-12 13:52:38 -08001055 "LS: Rcv %08x Drop %08x Abort %08x\n",
1056 atomic_read(&tgtp->rcv_ls_req_in),
1057 atomic_read(&tgtp->rcv_ls_req_drop),
1058 atomic_read(&tgtp->xmt_ls_abort));
1059 if (atomic_read(&tgtp->rcv_ls_req_in) !=
1060 atomic_read(&tgtp->rcv_ls_req_out)) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001061 len += scnprintf(buf + len, size - len,
James Smart2b65e182017-02-12 13:52:38 -08001062 "Rcv LS: in %08x != out %08x\n",
1063 atomic_read(&tgtp->rcv_ls_req_in),
1064 atomic_read(&tgtp->rcv_ls_req_out));
1065 }
1066
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001067 len += scnprintf(buf + len, size - len,
James Smart4b056682017-12-08 17:18:10 -08001068 "LS: Xmt %08x Drop %08x Cmpl %08x\n",
James Smart2b65e182017-02-12 13:52:38 -08001069 atomic_read(&tgtp->xmt_ls_rsp),
1070 atomic_read(&tgtp->xmt_ls_drop),
James Smart4b056682017-12-08 17:18:10 -08001071 atomic_read(&tgtp->xmt_ls_rsp_cmpl));
1072
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001073 len += scnprintf(buf + len, size - len,
James Smart4b056682017-12-08 17:18:10 -08001074 "LS: RSP Abort %08x xb %08x Err %08x\n",
1075 atomic_read(&tgtp->xmt_ls_rsp_aborted),
1076 atomic_read(&tgtp->xmt_ls_rsp_xb_set),
James Smart2b65e182017-02-12 13:52:38 -08001077 atomic_read(&tgtp->xmt_ls_rsp_error));
1078
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001079 len += scnprintf(buf + len, size - len,
James Smart50738422017-08-01 15:12:40 -07001080 "FCP: Rcv %08x Defer %08x Release %08x "
1081 "Drop %08x\n",
James Smart2b65e182017-02-12 13:52:38 -08001082 atomic_read(&tgtp->rcv_fcp_cmd_in),
James Smart50738422017-08-01 15:12:40 -07001083 atomic_read(&tgtp->rcv_fcp_cmd_defer),
1084 atomic_read(&tgtp->xmt_fcp_release),
James Smart2b65e182017-02-12 13:52:38 -08001085 atomic_read(&tgtp->rcv_fcp_cmd_drop));
1086
1087 if (atomic_read(&tgtp->rcv_fcp_cmd_in) !=
1088 atomic_read(&tgtp->rcv_fcp_cmd_out)) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001089 len += scnprintf(buf + len, size - len,
James Smart2b65e182017-02-12 13:52:38 -08001090 "Rcv FCP: in %08x != out %08x\n",
1091 atomic_read(&tgtp->rcv_fcp_cmd_in),
1092 atomic_read(&tgtp->rcv_fcp_cmd_out));
1093 }
1094
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001095 len += scnprintf(buf + len, size - len,
James Smart86c67372017-04-21 16:05:04 -07001096 "FCP Rsp: read %08x readrsp %08x "
1097 "write %08x rsp %08x\n",
James Smart2b65e182017-02-12 13:52:38 -08001098 atomic_read(&tgtp->xmt_fcp_read),
1099 atomic_read(&tgtp->xmt_fcp_read_rsp),
1100 atomic_read(&tgtp->xmt_fcp_write),
1101 atomic_read(&tgtp->xmt_fcp_rsp));
1102
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001103 len += scnprintf(buf + len, size - len,
James Smart2b65e182017-02-12 13:52:38 -08001104 "FCP Rsp Cmpl: %08x err %08x drop %08x\n",
1105 atomic_read(&tgtp->xmt_fcp_rsp_cmpl),
1106 atomic_read(&tgtp->xmt_fcp_rsp_error),
1107 atomic_read(&tgtp->xmt_fcp_rsp_drop));
1108
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001109 len += scnprintf(buf + len, size - len,
James Smart4b056682017-12-08 17:18:10 -08001110 "FCP Rsp Abort: %08x xb %08x xricqe %08x\n",
1111 atomic_read(&tgtp->xmt_fcp_rsp_aborted),
1112 atomic_read(&tgtp->xmt_fcp_rsp_xb_set),
1113 atomic_read(&tgtp->xmt_fcp_xri_abort_cqe));
1114
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001115 len += scnprintf(buf + len, size - len,
James Smart547077a2017-05-15 15:20:40 -07001116 "ABORT: Xmt %08x Cmpl %08x\n",
1117 atomic_read(&tgtp->xmt_fcp_abort),
1118 atomic_read(&tgtp->xmt_fcp_abort_cmpl));
1119
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001120 len += scnprintf(buf + len, size - len,
James Smart547077a2017-05-15 15:20:40 -07001121 "ABORT: Sol %08x Usol %08x Err %08x Cmpl %08x",
1122 atomic_read(&tgtp->xmt_abort_sol),
1123 atomic_read(&tgtp->xmt_abort_unsol),
James Smart2b65e182017-02-12 13:52:38 -08001124 atomic_read(&tgtp->xmt_abort_rsp),
James Smart547077a2017-05-15 15:20:40 -07001125 atomic_read(&tgtp->xmt_abort_rsp_error));
James Smart2b65e182017-02-12 13:52:38 -08001126
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001127 len += scnprintf(buf + len, size - len, "\n");
James Smart86c67372017-04-21 16:05:04 -07001128
1129 cnt = 0;
James Smart5e5b5112019-01-28 11:14:22 -08001130 spin_lock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
James Smart86c67372017-04-21 16:05:04 -07001131 list_for_each_entry_safe(ctxp, next_ctxp,
1132 &phba->sli4_hba.lpfc_abts_nvmet_ctx_list,
1133 list) {
1134 cnt++;
1135 }
James Smart5e5b5112019-01-28 11:14:22 -08001136 spin_unlock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
James Smart86c67372017-04-21 16:05:04 -07001137 if (cnt) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001138 len += scnprintf(buf + len, size - len,
James Smart86c67372017-04-21 16:05:04 -07001139 "ABORT: %d ctx entries\n", cnt);
James Smart5e5b5112019-01-28 11:14:22 -08001140 spin_lock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
James Smart86c67372017-04-21 16:05:04 -07001141 list_for_each_entry_safe(ctxp, next_ctxp,
1142 &phba->sli4_hba.lpfc_abts_nvmet_ctx_list,
1143 list) {
1144 if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ))
1145 break;
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001146 len += scnprintf(buf + len, size - len,
James Smart86c67372017-04-21 16:05:04 -07001147 "Entry: oxid %x state %x "
1148 "flag %x\n",
1149 ctxp->oxid, ctxp->state,
1150 ctxp->flag);
1151 }
James Smart5e5b5112019-01-28 11:14:22 -08001152 spin_unlock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
James Smart86c67372017-04-21 16:05:04 -07001153 }
James Smarta8cf5df2017-05-15 15:20:46 -07001154
Dick Kennedy66d7ce92017-08-23 16:55:42 -07001155 /* Calculate outstanding IOs */
1156 tot = atomic_read(&tgtp->rcv_fcp_cmd_drop);
1157 tot += atomic_read(&tgtp->xmt_fcp_release);
1158 tot = atomic_read(&tgtp->rcv_fcp_cmd_in) - tot;
James Smart2cee7802017-06-01 21:07:02 -07001159
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001160 len += scnprintf(buf + len, size - len,
James Smart2cee7802017-06-01 21:07:02 -07001161 "IO_CTX: %08x WAIT: cur %08x tot %08x\n"
1162 "CTX Outstanding %08llx\n",
James Smart966bb5b2017-06-15 22:56:45 -07001163 phba->sli4_hba.nvmet_xri_cnt,
James Smarta8cf5df2017-05-15 15:20:46 -07001164 phba->sli4_hba.nvmet_io_wait_cnt,
James Smart2cee7802017-06-01 21:07:02 -07001165 phba->sli4_hba.nvmet_io_wait_total,
1166 tot);
James Smart2b65e182017-02-12 13:52:38 -08001167 } else {
James Smartf6e84792019-01-28 11:14:38 -08001168 if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_NVME))
James Smartbd2cdd52017-02-12 13:52:33 -08001169 return len;
1170
James Smart4b056682017-12-08 17:18:10 -08001171 localport = vport->localport;
1172 if (!localport)
1173 return len;
1174 lport = (struct lpfc_nvme_lport *)localport->private;
1175 if (!lport)
1176 return len;
1177
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001178 len += scnprintf(buf + len, size - len,
James Smart4c47efc2019-01-28 11:14:25 -08001179 "\nNVME HDWQ Statistics\n");
James Smart66a210f2018-04-09 14:24:23 -07001180
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001181 len += scnprintf(buf + len, size - len,
James Smart66a210f2018-04-09 14:24:23 -07001182 "LS: Xmt %016x Cmpl %016x\n",
1183 atomic_read(&lport->fc4NvmeLsRequests),
1184 atomic_read(&lport->fc4NvmeLsCmpls));
1185
James Smart66a210f2018-04-09 14:24:23 -07001186 totin = 0;
1187 totout = 0;
James Smartcdb42be2019-01-28 11:14:21 -08001188 for (i = 0; i < phba->cfg_hdw_queue; i++) {
James Smart4c47efc2019-01-28 11:14:25 -08001189 cstat = &phba->sli4_hba.hdwq[i].nvme_cstat;
1190 tot = cstat->io_cmpls;
James Smart66a210f2018-04-09 14:24:23 -07001191 totin += tot;
James Smart4c47efc2019-01-28 11:14:25 -08001192 data1 = cstat->input_requests;
1193 data2 = cstat->output_requests;
1194 data3 = cstat->control_requests;
James Smart66a210f2018-04-09 14:24:23 -07001195 totout += (data1 + data2 + data3);
1196
1197 /* Limit to 32, debugfs display buffer limitation */
1198 if (i >= 32)
1199 continue;
1200
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001201 len += scnprintf(buf + len, PAGE_SIZE - len,
James Smart4c47efc2019-01-28 11:14:25 -08001202 "HDWQ (%d): Rd %016llx Wr %016llx "
James Smart66a210f2018-04-09 14:24:23 -07001203 "IO %016llx ",
1204 i, data1, data2, data3);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001205 len += scnprintf(buf + len, PAGE_SIZE - len,
James Smart66a210f2018-04-09 14:24:23 -07001206 "Cmpl %016llx OutIO %016llx\n",
1207 tot, ((data1 + data2 + data3) - tot));
1208 }
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001209 len += scnprintf(buf + len, PAGE_SIZE - len,
James Smart66a210f2018-04-09 14:24:23 -07001210 "Total FCP Cmpl %016llx Issue %016llx "
1211 "OutIO %016llx\n",
1212 totin, totout, totout - totin);
1213
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001214 len += scnprintf(buf + len, size - len,
James Smart4b056682017-12-08 17:18:10 -08001215 "LS Xmt Err: Abrt %08x Err %08x "
1216 "Cmpl Err: xb %08x Err %08x\n",
1217 atomic_read(&lport->xmt_ls_abort),
1218 atomic_read(&lport->xmt_ls_err),
1219 atomic_read(&lport->cmpl_ls_xb),
1220 atomic_read(&lport->cmpl_ls_err));
1221
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001222 len += scnprintf(buf + len, size - len,
James Smart4b056682017-12-08 17:18:10 -08001223 "FCP Xmt Err: noxri %06x nondlp %06x "
James Smart44c27572018-05-04 20:37:56 -07001224 "qdepth %06x wqerr %06x err %06x Abrt %06x\n",
James Smart4b056682017-12-08 17:18:10 -08001225 atomic_read(&lport->xmt_fcp_noxri),
1226 atomic_read(&lport->xmt_fcp_bad_ndlp),
1227 atomic_read(&lport->xmt_fcp_qdepth),
1228 atomic_read(&lport->xmt_fcp_wqerr),
James Smart44c27572018-05-04 20:37:56 -07001229 atomic_read(&lport->xmt_fcp_err),
James Smart4b056682017-12-08 17:18:10 -08001230 atomic_read(&lport->xmt_fcp_abort));
1231
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001232 len += scnprintf(buf + len, size - len,
James Smart4b056682017-12-08 17:18:10 -08001233 "FCP Cmpl Err: xb %08x Err %08x\n",
1234 atomic_read(&lport->cmpl_fcp_xb),
1235 atomic_read(&lport->cmpl_fcp_err));
1236
James Smartbd2cdd52017-02-12 13:52:33 -08001237 }
1238
1239 return len;
1240}
1241
James Smart4c47efc2019-01-28 11:14:25 -08001242/**
1243 * lpfc_debugfs_scsistat_data - Dump target node list to a buffer
1244 * @vport: The vport to gather target node info from.
1245 * @buf: The buffer to dump log into.
1246 * @size: The maximum amount of data to process.
1247 *
1248 * Description:
1249 * This routine dumps the SCSI statistics associated with @vport
1250 *
1251 * Return Value:
1252 * This routine returns the amount of bytes that were dumped into @buf and will
1253 * not exceed @size.
1254 **/
1255static int
1256lpfc_debugfs_scsistat_data(struct lpfc_vport *vport, char *buf, int size)
1257{
1258 int len;
1259 struct lpfc_hba *phba = vport->phba;
1260 struct lpfc_fc4_ctrl_stat *cstat;
1261 u64 data1, data2, data3;
1262 u64 tot, totin, totout;
1263 int i;
1264 char tmp[LPFC_MAX_SCSI_INFO_TMP_LEN] = {0};
1265
James Smartf6e84792019-01-28 11:14:38 -08001266 if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_FCP) ||
James Smart4c47efc2019-01-28 11:14:25 -08001267 (phba->sli_rev != LPFC_SLI_REV4))
1268 return 0;
1269
1270 scnprintf(buf, size, "SCSI HDWQ Statistics\n");
1271
1272 totin = 0;
1273 totout = 0;
1274 for (i = 0; i < phba->cfg_hdw_queue; i++) {
1275 cstat = &phba->sli4_hba.hdwq[i].scsi_cstat;
1276 tot = cstat->io_cmpls;
1277 totin += tot;
1278 data1 = cstat->input_requests;
1279 data2 = cstat->output_requests;
1280 data3 = cstat->control_requests;
1281 totout += (data1 + data2 + data3);
1282
1283 scnprintf(tmp, sizeof(tmp), "HDWQ (%d): Rd %016llx Wr %016llx "
1284 "IO %016llx ", i, data1, data2, data3);
1285 if (strlcat(buf, tmp, size) >= size)
1286 goto buffer_done;
1287
1288 scnprintf(tmp, sizeof(tmp), "Cmpl %016llx OutIO %016llx\n",
1289 tot, ((data1 + data2 + data3) - tot));
1290 if (strlcat(buf, tmp, size) >= size)
1291 goto buffer_done;
1292 }
1293 scnprintf(tmp, sizeof(tmp), "Total FCP Cmpl %016llx Issue %016llx "
1294 "OutIO %016llx\n", totin, totout, totout - totin);
1295 strlcat(buf, tmp, size);
1296
1297buffer_done:
1298 len = strnlen(buf, size);
1299
1300 return len;
1301}
James Smartbd2cdd52017-02-12 13:52:33 -08001302
1303/**
1304 * lpfc_debugfs_nvmektime_data - Dump target node list to a buffer
1305 * @vport: The vport to gather target node info from.
1306 * @buf: The buffer to dump log into.
1307 * @size: The maximum amount of data to process.
1308 *
1309 * Description:
1310 * This routine dumps the NVME statistics associated with @vport
1311 *
1312 * Return Value:
1313 * This routine returns the amount of bytes that were dumped into @buf and will
1314 * not exceed @size.
1315 **/
1316static int
1317lpfc_debugfs_nvmektime_data(struct lpfc_vport *vport, char *buf, int size)
1318{
1319 struct lpfc_hba *phba = vport->phba;
1320 int len = 0;
1321
1322 if (phba->nvmet_support == 0) {
1323 /* NVME Initiator */
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001324 len += scnprintf(buf + len, PAGE_SIZE - len,
James Smartbd2cdd52017-02-12 13:52:33 -08001325 "ktime %s: Total Samples: %lld\n",
1326 (phba->ktime_on ? "Enabled" : "Disabled"),
1327 phba->ktime_data_samples);
1328 if (phba->ktime_data_samples == 0)
1329 return len;
1330
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001331 len += scnprintf(
James Smartbd2cdd52017-02-12 13:52:33 -08001332 buf + len, PAGE_SIZE - len,
1333 "Segment 1: Last NVME Cmd cmpl "
1334 "done -to- Start of next NVME cnd (in driver)\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001335 len += scnprintf(
James Smartbd2cdd52017-02-12 13:52:33 -08001336 buf + len, PAGE_SIZE - len,
1337 "avg:%08lld min:%08lld max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001338 div_u64(phba->ktime_seg1_total,
1339 phba->ktime_data_samples),
James Smartbd2cdd52017-02-12 13:52:33 -08001340 phba->ktime_seg1_min,
1341 phba->ktime_seg1_max);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001342 len += scnprintf(
James Smartbd2cdd52017-02-12 13:52:33 -08001343 buf + len, PAGE_SIZE - len,
1344 "Segment 2: Driver start of NVME cmd "
1345 "-to- Firmware WQ doorbell\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001346 len += scnprintf(
James Smartbd2cdd52017-02-12 13:52:33 -08001347 buf + len, PAGE_SIZE - len,
1348 "avg:%08lld min:%08lld max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001349 div_u64(phba->ktime_seg2_total,
1350 phba->ktime_data_samples),
James Smartbd2cdd52017-02-12 13:52:33 -08001351 phba->ktime_seg2_min,
1352 phba->ktime_seg2_max);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001353 len += scnprintf(
James Smartbd2cdd52017-02-12 13:52:33 -08001354 buf + len, PAGE_SIZE - len,
1355 "Segment 3: Firmware WQ doorbell -to- "
1356 "MSI-X ISR cmpl\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001357 len += scnprintf(
James Smartbd2cdd52017-02-12 13:52:33 -08001358 buf + len, PAGE_SIZE - len,
1359 "avg:%08lld min:%08lld max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001360 div_u64(phba->ktime_seg3_total,
1361 phba->ktime_data_samples),
James Smartbd2cdd52017-02-12 13:52:33 -08001362 phba->ktime_seg3_min,
1363 phba->ktime_seg3_max);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001364 len += scnprintf(
James Smartbd2cdd52017-02-12 13:52:33 -08001365 buf + len, PAGE_SIZE - len,
1366 "Segment 4: MSI-X ISR cmpl -to- "
1367 "NVME cmpl done\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001368 len += scnprintf(
James Smartbd2cdd52017-02-12 13:52:33 -08001369 buf + len, PAGE_SIZE - len,
1370 "avg:%08lld min:%08lld max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001371 div_u64(phba->ktime_seg4_total,
1372 phba->ktime_data_samples),
James Smartbd2cdd52017-02-12 13:52:33 -08001373 phba->ktime_seg4_min,
1374 phba->ktime_seg4_max);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001375 len += scnprintf(
James Smartbd2cdd52017-02-12 13:52:33 -08001376 buf + len, PAGE_SIZE - len,
1377 "Total IO avg time: %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001378 div_u64(phba->ktime_seg1_total +
James Smartbd2cdd52017-02-12 13:52:33 -08001379 phba->ktime_seg2_total +
1380 phba->ktime_seg3_total +
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001381 phba->ktime_seg4_total,
James Smartbd2cdd52017-02-12 13:52:33 -08001382 phba->ktime_data_samples));
1383 return len;
1384 }
James Smart2b65e182017-02-12 13:52:38 -08001385
1386 /* NVME Target */
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001387 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001388 "ktime %s: Total Samples: %lld %lld\n",
1389 (phba->ktime_on ? "Enabled" : "Disabled"),
1390 phba->ktime_data_samples,
1391 phba->ktime_status_samples);
1392 if (phba->ktime_data_samples == 0)
1393 return len;
1394
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001395 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001396 "Segment 1: MSI-X ISR Rcv cmd -to- "
1397 "cmd pass to NVME Layer\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001398 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001399 "avg:%08lld min:%08lld max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001400 div_u64(phba->ktime_seg1_total,
1401 phba->ktime_data_samples),
James Smart2b65e182017-02-12 13:52:38 -08001402 phba->ktime_seg1_min,
1403 phba->ktime_seg1_max);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001404 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001405 "Segment 2: cmd pass to NVME Layer- "
1406 "-to- Driver rcv cmd OP (action)\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001407 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001408 "avg:%08lld min:%08lld max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001409 div_u64(phba->ktime_seg2_total,
1410 phba->ktime_data_samples),
James Smart2b65e182017-02-12 13:52:38 -08001411 phba->ktime_seg2_min,
1412 phba->ktime_seg2_max);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001413 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001414 "Segment 3: Driver rcv cmd OP -to- "
1415 "Firmware WQ doorbell: cmd\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001416 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001417 "avg:%08lld min:%08lld max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001418 div_u64(phba->ktime_seg3_total,
1419 phba->ktime_data_samples),
James Smart2b65e182017-02-12 13:52:38 -08001420 phba->ktime_seg3_min,
1421 phba->ktime_seg3_max);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001422 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001423 "Segment 4: Firmware WQ doorbell: cmd "
1424 "-to- MSI-X ISR for cmd cmpl\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001425 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001426 "avg:%08lld min:%08lld max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001427 div_u64(phba->ktime_seg4_total,
1428 phba->ktime_data_samples),
James Smart2b65e182017-02-12 13:52:38 -08001429 phba->ktime_seg4_min,
1430 phba->ktime_seg4_max);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001431 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001432 "Segment 5: MSI-X ISR for cmd cmpl "
1433 "-to- NVME layer passed cmd done\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001434 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001435 "avg:%08lld min:%08lld max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001436 div_u64(phba->ktime_seg5_total,
1437 phba->ktime_data_samples),
James Smart2b65e182017-02-12 13:52:38 -08001438 phba->ktime_seg5_min,
1439 phba->ktime_seg5_max);
1440
1441 if (phba->ktime_status_samples == 0) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001442 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001443 "Total: cmd received by MSI-X ISR "
1444 "-to- cmd completed on wire\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001445 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001446 "avg:%08lld min:%08lld "
1447 "max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001448 div_u64(phba->ktime_seg10_total,
1449 phba->ktime_data_samples),
James Smart2b65e182017-02-12 13:52:38 -08001450 phba->ktime_seg10_min,
1451 phba->ktime_seg10_max);
1452 return len;
1453 }
1454
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001455 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001456 "Segment 6: NVME layer passed cmd done "
1457 "-to- Driver rcv rsp status OP\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001458 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001459 "avg:%08lld min:%08lld max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001460 div_u64(phba->ktime_seg6_total,
1461 phba->ktime_status_samples),
James Smart2b65e182017-02-12 13:52:38 -08001462 phba->ktime_seg6_min,
1463 phba->ktime_seg6_max);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001464 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001465 "Segment 7: Driver rcv rsp status OP "
1466 "-to- Firmware WQ doorbell: status\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001467 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001468 "avg:%08lld min:%08lld max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001469 div_u64(phba->ktime_seg7_total,
1470 phba->ktime_status_samples),
James Smart2b65e182017-02-12 13:52:38 -08001471 phba->ktime_seg7_min,
1472 phba->ktime_seg7_max);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001473 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001474 "Segment 8: Firmware WQ doorbell: status"
1475 " -to- MSI-X ISR for status cmpl\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001476 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001477 "avg:%08lld min:%08lld max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001478 div_u64(phba->ktime_seg8_total,
1479 phba->ktime_status_samples),
James Smart2b65e182017-02-12 13:52:38 -08001480 phba->ktime_seg8_min,
1481 phba->ktime_seg8_max);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001482 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001483 "Segment 9: MSI-X ISR for status cmpl "
1484 "-to- NVME layer passed status done\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001485 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001486 "avg:%08lld min:%08lld max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001487 div_u64(phba->ktime_seg9_total,
1488 phba->ktime_status_samples),
James Smart2b65e182017-02-12 13:52:38 -08001489 phba->ktime_seg9_min,
1490 phba->ktime_seg9_max);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001491 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001492 "Total: cmd received by MSI-X ISR -to- "
1493 "cmd completed on wire\n");
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001494 len += scnprintf(buf + len, PAGE_SIZE-len,
James Smart2b65e182017-02-12 13:52:38 -08001495 "avg:%08lld min:%08lld max %08lld\n",
Arnd Bergmann90ec7c92017-02-27 21:31:43 +01001496 div_u64(phba->ktime_seg10_total,
1497 phba->ktime_status_samples),
James Smart2b65e182017-02-12 13:52:38 -08001498 phba->ktime_seg10_min,
1499 phba->ktime_seg10_max);
James Smartbd2cdd52017-02-12 13:52:33 -08001500 return len;
1501}
1502
1503/**
1504 * lpfc_debugfs_nvmeio_trc_data - Dump NVME IO trace list to a buffer
1505 * @phba: The phba to gather target node info from.
1506 * @buf: The buffer to dump log into.
1507 * @size: The maximum amount of data to process.
1508 *
1509 * Description:
1510 * This routine dumps the NVME IO trace associated with @phba
1511 *
1512 * Return Value:
1513 * This routine returns the amount of bytes that were dumped into @buf and will
1514 * not exceed @size.
1515 **/
1516static int
1517lpfc_debugfs_nvmeio_trc_data(struct lpfc_hba *phba, char *buf, int size)
1518{
1519 struct lpfc_debugfs_nvmeio_trc *dtp;
1520 int i, state, index, skip;
1521 int len = 0;
1522
1523 state = phba->nvmeio_trc_on;
1524
1525 index = (atomic_read(&phba->nvmeio_trc_cnt) + 1) &
1526 (phba->nvmeio_trc_size - 1);
1527 skip = phba->nvmeio_trc_output_idx;
1528
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001529 len += scnprintf(buf + len, size - len,
James Smartbd2cdd52017-02-12 13:52:33 -08001530 "%s IO Trace %s: next_idx %d skip %d size %d\n",
1531 (phba->nvmet_support ? "NVME" : "NVMET"),
1532 (state ? "Enabled" : "Disabled"),
1533 index, skip, phba->nvmeio_trc_size);
1534
1535 if (!phba->nvmeio_trc || state)
1536 return len;
1537
1538 /* trace MUST bhe off to continue */
1539
1540 for (i = index; i < phba->nvmeio_trc_size; i++) {
1541 if (skip) {
1542 skip--;
1543 continue;
1544 }
1545 dtp = phba->nvmeio_trc + i;
1546 phba->nvmeio_trc_output_idx++;
1547
1548 if (!dtp->fmt)
1549 continue;
1550
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001551 len += scnprintf(buf + len, size - len, dtp->fmt,
James Smartbd2cdd52017-02-12 13:52:33 -08001552 dtp->data1, dtp->data2, dtp->data3);
1553
1554 if (phba->nvmeio_trc_output_idx >= phba->nvmeio_trc_size) {
1555 phba->nvmeio_trc_output_idx = 0;
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001556 len += scnprintf(buf + len, size - len,
James Smartbd2cdd52017-02-12 13:52:33 -08001557 "Trace Complete\n");
1558 goto out;
1559 }
1560
1561 if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ)) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001562 len += scnprintf(buf + len, size - len,
James Smartbd2cdd52017-02-12 13:52:33 -08001563 "Trace Continue (%d of %d)\n",
1564 phba->nvmeio_trc_output_idx,
1565 phba->nvmeio_trc_size);
1566 goto out;
1567 }
1568 }
1569 for (i = 0; i < index; i++) {
1570 if (skip) {
1571 skip--;
1572 continue;
1573 }
1574 dtp = phba->nvmeio_trc + i;
1575 phba->nvmeio_trc_output_idx++;
1576
1577 if (!dtp->fmt)
1578 continue;
1579
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001580 len += scnprintf(buf + len, size - len, dtp->fmt,
James Smartbd2cdd52017-02-12 13:52:33 -08001581 dtp->data1, dtp->data2, dtp->data3);
1582
1583 if (phba->nvmeio_trc_output_idx >= phba->nvmeio_trc_size) {
1584 phba->nvmeio_trc_output_idx = 0;
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001585 len += scnprintf(buf + len, size - len,
James Smartbd2cdd52017-02-12 13:52:33 -08001586 "Trace Complete\n");
1587 goto out;
1588 }
1589
1590 if (len >= (size - LPFC_DEBUG_OUT_LINE_SZ)) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001591 len += scnprintf(buf + len, size - len,
James Smartbd2cdd52017-02-12 13:52:33 -08001592 "Trace Continue (%d of %d)\n",
1593 phba->nvmeio_trc_output_idx,
1594 phba->nvmeio_trc_size);
1595 goto out;
1596 }
1597 }
1598
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001599 len += scnprintf(buf + len, size - len,
James Smartbd2cdd52017-02-12 13:52:33 -08001600 "Trace Done\n");
1601out:
1602 return len;
1603}
1604
1605/**
1606 * lpfc_debugfs_cpucheck_data - Dump target node list to a buffer
1607 * @vport: The vport to gather target node info from.
1608 * @buf: The buffer to dump log into.
1609 * @size: The maximum amount of data to process.
1610 *
1611 * Description:
1612 * This routine dumps the NVME statistics associated with @vport
1613 *
1614 * Return Value:
1615 * This routine returns the amount of bytes that were dumped into @buf and will
1616 * not exceed @size.
1617 **/
1618static int
1619lpfc_debugfs_cpucheck_data(struct lpfc_vport *vport, char *buf, int size)
1620{
1621 struct lpfc_hba *phba = vport->phba;
James Smart63df6d62019-01-28 11:14:24 -08001622 struct lpfc_sli4_hdw_queue *qp;
James Smart6a828b02019-01-28 11:14:31 -08001623 int i, j, max_cnt;
James Smartbd2cdd52017-02-12 13:52:33 -08001624 int len = 0;
James Smart63df6d62019-01-28 11:14:24 -08001625 uint32_t tot_xmt;
1626 uint32_t tot_rcv;
1627 uint32_t tot_cmpl;
James Smartbd2cdd52017-02-12 13:52:33 -08001628
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001629 len += scnprintf(buf + len, PAGE_SIZE - len,
James Smart2b65e182017-02-12 13:52:38 -08001630 "CPUcheck %s ",
James Smart63df6d62019-01-28 11:14:24 -08001631 (phba->cpucheck_on & LPFC_CHECK_NVME_IO ?
1632 "Enabled" : "Disabled"));
1633 if (phba->nvmet_support) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001634 len += scnprintf(buf + len, PAGE_SIZE - len,
James Smart63df6d62019-01-28 11:14:24 -08001635 "%s\n",
1636 (phba->cpucheck_on & LPFC_CHECK_NVMET_RCV ?
1637 "Rcv Enabled\n" : "Rcv Disabled\n"));
1638 } else {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001639 len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
James Smart2b65e182017-02-12 13:52:38 -08001640 }
James Smart6a828b02019-01-28 11:14:31 -08001641 max_cnt = size - LPFC_DEBUG_OUT_LINE_SZ;
James Smart63df6d62019-01-28 11:14:24 -08001642
1643 for (i = 0; i < phba->cfg_hdw_queue; i++) {
1644 qp = &phba->sli4_hba.hdwq[i];
1645
1646 tot_rcv = 0;
1647 tot_xmt = 0;
1648 tot_cmpl = 0;
1649 for (j = 0; j < LPFC_CHECK_CPU_CNT; j++) {
1650 tot_xmt += qp->cpucheck_xmt_io[j];
1651 tot_cmpl += qp->cpucheck_cmpl_io[j];
1652 if (phba->nvmet_support)
1653 tot_rcv += qp->cpucheck_rcv_io[j];
1654 }
1655
1656 /* Only display Hardware Qs with something */
1657 if (!tot_xmt && !tot_cmpl && !tot_rcv)
1658 continue;
1659
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001660 len += scnprintf(buf + len, PAGE_SIZE - len,
James Smart63df6d62019-01-28 11:14:24 -08001661 "HDWQ %03d: ", i);
1662 for (j = 0; j < LPFC_CHECK_CPU_CNT; j++) {
1663 /* Only display non-zero counters */
1664 if (!qp->cpucheck_xmt_io[j] &&
1665 !qp->cpucheck_cmpl_io[j] &&
1666 !qp->cpucheck_rcv_io[j])
1667 continue;
1668 if (phba->nvmet_support) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001669 len += scnprintf(buf + len, PAGE_SIZE - len,
James Smart63df6d62019-01-28 11:14:24 -08001670 "CPU %03d: %x/%x/%x ", j,
1671 qp->cpucheck_rcv_io[j],
1672 qp->cpucheck_xmt_io[j],
1673 qp->cpucheck_cmpl_io[j]);
1674 } else {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001675 len += scnprintf(buf + len, PAGE_SIZE - len,
James Smart63df6d62019-01-28 11:14:24 -08001676 "CPU %03d: %x/%x ", j,
1677 qp->cpucheck_xmt_io[j],
1678 qp->cpucheck_cmpl_io[j]);
1679 }
1680 }
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001681 len += scnprintf(buf + len, PAGE_SIZE - len,
James Smart63df6d62019-01-28 11:14:24 -08001682 "Total: %x\n", tot_xmt);
James Smart6a828b02019-01-28 11:14:31 -08001683 if (len >= max_cnt) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001684 len += scnprintf(buf + len, PAGE_SIZE - len,
James Smart6a828b02019-01-28 11:14:31 -08001685 "Truncated ...\n");
1686 return len;
1687 }
James Smart63df6d62019-01-28 11:14:24 -08001688 }
James Smart858c9f62007-06-17 19:56:39 -05001689 return len;
1690}
James Smart2ea259e2017-02-12 13:52:27 -08001691
James Smart858c9f62007-06-17 19:56:39 -05001692#endif
1693
James Smarte59058c2008-08-24 21:49:00 -04001694/**
James Smart3621a712009-04-06 18:47:14 -04001695 * lpfc_debugfs_disc_trc - Store discovery trace log
James Smarte59058c2008-08-24 21:49:00 -04001696 * @vport: The vport to associate this trace string with for retrieval.
1697 * @mask: Log entry classification.
1698 * @fmt: Format string to be displayed when dumping the log.
1699 * @data1: 1st data parameter to be applied to @fmt.
1700 * @data2: 2nd data parameter to be applied to @fmt.
1701 * @data3: 3rd data parameter to be applied to @fmt.
1702 *
1703 * Description:
1704 * This routine is used by the driver code to add a debugfs log entry to the
1705 * discovery trace buffer associated with @vport. Only entries with a @mask that
1706 * match the current debugfs discovery mask will be saved. Entries that do not
1707 * match will be thrown away. @fmt, @data1, @data2, and @data3 are used like
1708 * printf when displaying the log.
1709 **/
James Smart858c9f62007-06-17 19:56:39 -05001710inline void
1711lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt,
1712 uint32_t data1, uint32_t data2, uint32_t data3)
1713{
James Smart923e4b62008-12-04 22:40:07 -05001714#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
James Smarta58cbd52007-08-02 11:09:43 -04001715 struct lpfc_debugfs_trc *dtp;
James Smart858c9f62007-06-17 19:56:39 -05001716 int index;
1717
1718 if (!(lpfc_debugfs_mask_disc_trc & mask))
1719 return;
1720
1721 if (!lpfc_debugfs_enable || !lpfc_debugfs_max_disc_trc ||
1722 !vport || !vport->disc_trc)
1723 return;
1724
1725 index = atomic_inc_return(&vport->disc_trc_cnt) &
1726 (lpfc_debugfs_max_disc_trc - 1);
1727 dtp = vport->disc_trc + index;
1728 dtp->fmt = fmt;
1729 dtp->data1 = data1;
1730 dtp->data2 = data2;
1731 dtp->data3 = data3;
James Smarta58cbd52007-08-02 11:09:43 -04001732 dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt);
1733 dtp->jif = jiffies;
1734#endif
1735 return;
1736}
1737
James Smarte59058c2008-08-24 21:49:00 -04001738/**
James Smart3621a712009-04-06 18:47:14 -04001739 * lpfc_debugfs_slow_ring_trc - Store slow ring trace log
James Smarte59058c2008-08-24 21:49:00 -04001740 * @phba: The phba to associate this trace string with for retrieval.
1741 * @fmt: Format string to be displayed when dumping the log.
1742 * @data1: 1st data parameter to be applied to @fmt.
1743 * @data2: 2nd data parameter to be applied to @fmt.
1744 * @data3: 3rd data parameter to be applied to @fmt.
1745 *
1746 * Description:
1747 * This routine is used by the driver code to add a debugfs log entry to the
1748 * discovery trace buffer associated with @vport. @fmt, @data1, @data2, and
1749 * @data3 are used like printf when displaying the log.
1750 **/
James Smarta58cbd52007-08-02 11:09:43 -04001751inline void
1752lpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt,
1753 uint32_t data1, uint32_t data2, uint32_t data3)
1754{
James Smart923e4b62008-12-04 22:40:07 -05001755#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
James Smarta58cbd52007-08-02 11:09:43 -04001756 struct lpfc_debugfs_trc *dtp;
1757 int index;
1758
1759 if (!lpfc_debugfs_enable || !lpfc_debugfs_max_slow_ring_trc ||
1760 !phba || !phba->slow_ring_trc)
1761 return;
1762
1763 index = atomic_inc_return(&phba->slow_ring_trc_cnt) &
1764 (lpfc_debugfs_max_slow_ring_trc - 1);
1765 dtp = phba->slow_ring_trc + index;
1766 dtp->fmt = fmt;
1767 dtp->data1 = data1;
1768 dtp->data2 = data2;
1769 dtp->data3 = data3;
1770 dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt);
James Smart858c9f62007-06-17 19:56:39 -05001771 dtp->jif = jiffies;
1772#endif
1773 return;
1774}
1775
James Smartbd2cdd52017-02-12 13:52:33 -08001776/**
1777 * lpfc_debugfs_nvme_trc - Store NVME/NVMET trace log
1778 * @phba: The phba to associate this trace string with for retrieval.
1779 * @fmt: Format string to be displayed when dumping the log.
1780 * @data1: 1st data parameter to be applied to @fmt.
1781 * @data2: 2nd data parameter to be applied to @fmt.
1782 * @data3: 3rd data parameter to be applied to @fmt.
1783 *
1784 * Description:
1785 * This routine is used by the driver code to add a debugfs log entry to the
1786 * nvme trace buffer associated with @phba. @fmt, @data1, @data2, and
1787 * @data3 are used like printf when displaying the log.
1788 **/
1789inline void
1790lpfc_debugfs_nvme_trc(struct lpfc_hba *phba, char *fmt,
1791 uint16_t data1, uint16_t data2, uint32_t data3)
1792{
1793#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
1794 struct lpfc_debugfs_nvmeio_trc *dtp;
1795 int index;
1796
1797 if (!phba->nvmeio_trc_on || !phba->nvmeio_trc)
1798 return;
1799
1800 index = atomic_inc_return(&phba->nvmeio_trc_cnt) &
1801 (phba->nvmeio_trc_size - 1);
1802 dtp = phba->nvmeio_trc + index;
1803 dtp->fmt = fmt;
1804 dtp->data1 = data1;
1805 dtp->data2 = data2;
1806 dtp->data3 = data3;
1807#endif
1808}
1809
James Smart923e4b62008-12-04 22:40:07 -05001810#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
James Smarte59058c2008-08-24 21:49:00 -04001811/**
James Smart3621a712009-04-06 18:47:14 -04001812 * lpfc_debugfs_disc_trc_open - Open the discovery trace log
James Smarte59058c2008-08-24 21:49:00 -04001813 * @inode: The inode pointer that contains a vport pointer.
1814 * @file: The file pointer to attach the log output.
1815 *
1816 * Description:
1817 * This routine is the entry point for the debugfs open file operation. It gets
1818 * the vport from the i_private field in @inode, allocates the necessary buffer
1819 * for the log, fills the buffer from the in-memory log for this vport, and then
1820 * returns a pointer to that log in the private_data field in @file.
1821 *
1822 * Returns:
Geert Uytterhoeven79ce48d2015-05-21 14:11:33 +02001823 * This function returns zero if successful. On error it will return a negative
James Smarte59058c2008-08-24 21:49:00 -04001824 * error value.
1825 **/
James Smart858c9f62007-06-17 19:56:39 -05001826static int
1827lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file)
1828{
1829 struct lpfc_vport *vport = inode->i_private;
1830 struct lpfc_debug *debug;
1831 int size;
1832 int rc = -ENOMEM;
1833
1834 if (!lpfc_debugfs_max_disc_trc) {
Colin Ian King258f84f2019-02-12 15:29:45 +00001835 rc = -ENOSPC;
James Smart858c9f62007-06-17 19:56:39 -05001836 goto out;
1837 }
1838
1839 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
1840 if (!debug)
1841 goto out;
1842
James Smarte59058c2008-08-24 21:49:00 -04001843 /* Round to page boundary */
James Smarta58cbd52007-08-02 11:09:43 -04001844 size = (lpfc_debugfs_max_disc_trc * LPFC_DEBUG_TRC_ENTRY_SIZE);
James Smart858c9f62007-06-17 19:56:39 -05001845 size = PAGE_ALIGN(size);
1846
1847 debug->buffer = kmalloc(size, GFP_KERNEL);
1848 if (!debug->buffer) {
1849 kfree(debug);
1850 goto out;
1851 }
1852
1853 debug->len = lpfc_debugfs_disc_trc_data(vport, debug->buffer, size);
1854 file->private_data = debug;
1855
1856 rc = 0;
1857out:
1858 return rc;
1859}
1860
James Smarte59058c2008-08-24 21:49:00 -04001861/**
James Smart3621a712009-04-06 18:47:14 -04001862 * lpfc_debugfs_slow_ring_trc_open - Open the Slow Ring trace log
James Smarte59058c2008-08-24 21:49:00 -04001863 * @inode: The inode pointer that contains a vport pointer.
1864 * @file: The file pointer to attach the log output.
1865 *
1866 * Description:
1867 * This routine is the entry point for the debugfs open file operation. It gets
1868 * the vport from the i_private field in @inode, allocates the necessary buffer
1869 * for the log, fills the buffer from the in-memory log for this vport, and then
1870 * returns a pointer to that log in the private_data field in @file.
1871 *
1872 * Returns:
Geert Uytterhoeven79ce48d2015-05-21 14:11:33 +02001873 * This function returns zero if successful. On error it will return a negative
James Smarte59058c2008-08-24 21:49:00 -04001874 * error value.
1875 **/
James Smart858c9f62007-06-17 19:56:39 -05001876static int
James Smarta58cbd52007-08-02 11:09:43 -04001877lpfc_debugfs_slow_ring_trc_open(struct inode *inode, struct file *file)
1878{
1879 struct lpfc_hba *phba = inode->i_private;
1880 struct lpfc_debug *debug;
1881 int size;
1882 int rc = -ENOMEM;
1883
1884 if (!lpfc_debugfs_max_slow_ring_trc) {
Colin Ian King258f84f2019-02-12 15:29:45 +00001885 rc = -ENOSPC;
James Smarta58cbd52007-08-02 11:09:43 -04001886 goto out;
1887 }
1888
1889 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
1890 if (!debug)
1891 goto out;
1892
James Smarte59058c2008-08-24 21:49:00 -04001893 /* Round to page boundary */
James Smarta58cbd52007-08-02 11:09:43 -04001894 size = (lpfc_debugfs_max_slow_ring_trc * LPFC_DEBUG_TRC_ENTRY_SIZE);
1895 size = PAGE_ALIGN(size);
1896
1897 debug->buffer = kmalloc(size, GFP_KERNEL);
1898 if (!debug->buffer) {
1899 kfree(debug);
1900 goto out;
1901 }
1902
1903 debug->len = lpfc_debugfs_slow_ring_trc_data(phba, debug->buffer, size);
1904 file->private_data = debug;
1905
1906 rc = 0;
1907out:
1908 return rc;
1909}
1910
James Smarte59058c2008-08-24 21:49:00 -04001911/**
James Smart3621a712009-04-06 18:47:14 -04001912 * lpfc_debugfs_hbqinfo_open - Open the hbqinfo debugfs buffer
James Smarte59058c2008-08-24 21:49:00 -04001913 * @inode: The inode pointer that contains a vport pointer.
1914 * @file: The file pointer to attach the log output.
1915 *
1916 * Description:
1917 * This routine is the entry point for the debugfs open file operation. It gets
1918 * the vport from the i_private field in @inode, allocates the necessary buffer
1919 * for the log, fills the buffer from the in-memory log for this vport, and then
1920 * returns a pointer to that log in the private_data field in @file.
1921 *
1922 * Returns:
Geert Uytterhoeven79ce48d2015-05-21 14:11:33 +02001923 * This function returns zero if successful. On error it will return a negative
James Smarte59058c2008-08-24 21:49:00 -04001924 * error value.
1925 **/
James Smarta58cbd52007-08-02 11:09:43 -04001926static int
James Smart78b2d852007-08-02 11:10:21 -04001927lpfc_debugfs_hbqinfo_open(struct inode *inode, struct file *file)
1928{
1929 struct lpfc_hba *phba = inode->i_private;
1930 struct lpfc_debug *debug;
1931 int rc = -ENOMEM;
1932
1933 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
1934 if (!debug)
1935 goto out;
1936
James Smarte59058c2008-08-24 21:49:00 -04001937 /* Round to page boundary */
James Smart78b2d852007-08-02 11:10:21 -04001938 debug->buffer = kmalloc(LPFC_HBQINFO_SIZE, GFP_KERNEL);
1939 if (!debug->buffer) {
1940 kfree(debug);
1941 goto out;
1942 }
1943
1944 debug->len = lpfc_debugfs_hbqinfo_data(phba, debug->buffer,
1945 LPFC_HBQINFO_SIZE);
1946 file->private_data = debug;
1947
1948 rc = 0;
1949out:
1950 return rc;
1951}
1952
James Smarte59058c2008-08-24 21:49:00 -04001953/**
James Smartc4908502019-01-28 11:14:28 -08001954 * lpfc_debugfs_multixripools_open - Open the multixripool debugfs buffer
1955 * @inode: The inode pointer that contains a hba pointer.
1956 * @file: The file pointer to attach the log output.
1957 *
1958 * Description:
1959 * This routine is the entry point for the debugfs open file operation. It gets
1960 * the hba from the i_private field in @inode, allocates the necessary buffer
1961 * for the log, fills the buffer from the in-memory log for this hba, and then
1962 * returns a pointer to that log in the private_data field in @file.
1963 *
1964 * Returns:
1965 * This function returns zero if successful. On error it will return a negative
1966 * error value.
1967 **/
1968static int
1969lpfc_debugfs_multixripools_open(struct inode *inode, struct file *file)
1970{
1971 struct lpfc_hba *phba = inode->i_private;
1972 struct lpfc_debug *debug;
1973 int rc = -ENOMEM;
1974
1975 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
1976 if (!debug)
1977 goto out;
1978
1979 /* Round to page boundary */
1980 debug->buffer = kzalloc(LPFC_DUMP_MULTIXRIPOOL_SIZE, GFP_KERNEL);
1981 if (!debug->buffer) {
1982 kfree(debug);
1983 goto out;
1984 }
1985
James Smart6a828b02019-01-28 11:14:31 -08001986 debug->len = lpfc_debugfs_multixripools_data(
1987 phba, debug->buffer, LPFC_DUMP_MULTIXRIPOOL_SIZE);
James Smartc4908502019-01-28 11:14:28 -08001988
1989 debug->i_private = inode->i_private;
1990 file->private_data = debug;
1991
1992 rc = 0;
1993out:
1994 return rc;
1995}
1996
James Smart6a828b02019-01-28 11:14:31 -08001997#ifdef LPFC_HDWQ_LOCK_STAT
James Smartc4908502019-01-28 11:14:28 -08001998/**
James Smart6a828b02019-01-28 11:14:31 -08001999 * lpfc_debugfs_lockstat_open - Open the lockstat debugfs buffer
James Smart5e5b5112019-01-28 11:14:22 -08002000 * @inode: The inode pointer that contains a vport pointer.
2001 * @file: The file pointer to attach the log output.
2002 *
2003 * Description:
2004 * This routine is the entry point for the debugfs open file operation. It gets
2005 * the vport from the i_private field in @inode, allocates the necessary buffer
2006 * for the log, fills the buffer from the in-memory log for this vport, and then
2007 * returns a pointer to that log in the private_data field in @file.
2008 *
2009 * Returns:
2010 * This function returns zero if successful. On error it will return a negative
2011 * error value.
2012 **/
2013static int
James Smart6a828b02019-01-28 11:14:31 -08002014lpfc_debugfs_lockstat_open(struct inode *inode, struct file *file)
James Smart5e5b5112019-01-28 11:14:22 -08002015{
2016 struct lpfc_hba *phba = inode->i_private;
2017 struct lpfc_debug *debug;
2018 int rc = -ENOMEM;
2019
2020 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2021 if (!debug)
2022 goto out;
2023
2024 /* Round to page boundary */
2025 debug->buffer = kmalloc(LPFC_HDWQINFO_SIZE, GFP_KERNEL);
2026 if (!debug->buffer) {
2027 kfree(debug);
2028 goto out;
2029 }
2030
James Smart6a828b02019-01-28 11:14:31 -08002031 debug->len = lpfc_debugfs_lockstat_data(phba, debug->buffer,
James Smart5e5b5112019-01-28 11:14:22 -08002032 LPFC_HBQINFO_SIZE);
2033 file->private_data = debug;
2034
2035 rc = 0;
2036out:
2037 return rc;
2038}
2039
James Smart6a828b02019-01-28 11:14:31 -08002040static ssize_t
2041lpfc_debugfs_lockstat_write(struct file *file, const char __user *buf,
2042 size_t nbytes, loff_t *ppos)
2043{
2044 struct lpfc_debug *debug = file->private_data;
2045 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
2046 struct lpfc_sli4_hdw_queue *qp;
2047 char mybuf[64];
2048 char *pbuf;
2049 int i;
2050
2051 /* Protect copy from user */
2052 if (!access_ok(buf, nbytes))
2053 return -EFAULT;
2054
2055 memset(mybuf, 0, sizeof(mybuf));
2056
2057 if (copy_from_user(mybuf, buf, nbytes))
2058 return -EFAULT;
2059 pbuf = &mybuf[0];
2060
2061 if ((strncmp(pbuf, "reset", strlen("reset")) == 0) ||
2062 (strncmp(pbuf, "zero", strlen("zero")) == 0)) {
2063 for (i = 0; i < phba->cfg_hdw_queue; i++) {
2064 qp = &phba->sli4_hba.hdwq[i];
2065 qp->lock_conflict.alloc_xri_get = 0;
2066 qp->lock_conflict.alloc_xri_put = 0;
2067 qp->lock_conflict.free_xri = 0;
2068 qp->lock_conflict.wq_access = 0;
2069 qp->lock_conflict.alloc_pvt_pool = 0;
2070 qp->lock_conflict.mv_from_pvt_pool = 0;
2071 qp->lock_conflict.mv_to_pub_pool = 0;
2072 qp->lock_conflict.mv_to_pvt_pool = 0;
2073 qp->lock_conflict.free_pvt_pool = 0;
2074 qp->lock_conflict.free_pub_pool = 0;
2075 qp->lock_conflict.wq_access = 0;
2076 }
2077 }
2078 return nbytes;
2079}
2080#endif
2081
YueHaibing7b10db52019-10-28 21:25:56 +08002082static int lpfc_debugfs_ras_log_data(struct lpfc_hba *phba,
2083 char *buffer, int size)
James Smart95bfc6d2019-10-18 14:18:27 -07002084{
2085 int copied = 0;
2086 struct lpfc_dmabuf *dmabuf, *next;
2087
2088 spin_lock_irq(&phba->hbalock);
2089 if (phba->ras_fwlog.state != ACTIVE) {
2090 spin_unlock_irq(&phba->hbalock);
2091 return -EINVAL;
2092 }
2093 spin_unlock_irq(&phba->hbalock);
2094
2095 list_for_each_entry_safe(dmabuf, next,
2096 &phba->ras_fwlog.fwlog_buff_list, list) {
2097 memcpy(buffer + copied, dmabuf->virt, LPFC_RAS_MAX_ENTRY_SIZE);
2098 copied += LPFC_RAS_MAX_ENTRY_SIZE;
2099 if (size > copied)
2100 break;
2101 }
2102 return copied;
2103}
2104
2105static int
2106lpfc_debugfs_ras_log_release(struct inode *inode, struct file *file)
2107{
2108 struct lpfc_debug *debug = file->private_data;
2109
2110 vfree(debug->buffer);
2111 kfree(debug);
2112
2113 return 0;
2114}
2115
2116/**
2117 * lpfc_debugfs_ras_log_open - Open the RAS log debugfs buffer
2118 * @inode: The inode pointer that contains a vport pointer.
2119 * @file: The file pointer to attach the log output.
2120 *
2121 * Description:
2122 * This routine is the entry point for the debugfs open file operation. It gets
2123 * the vport from the i_private field in @inode, allocates the necessary buffer
2124 * for the log, fills the buffer from the in-memory log for this vport, and then
2125 * returns a pointer to that log in the private_data field in @file.
2126 *
2127 * Returns:
2128 * This function returns zero if successful. On error it will return a negative
2129 * error value.
2130 **/
2131static int
2132lpfc_debugfs_ras_log_open(struct inode *inode, struct file *file)
2133{
2134 struct lpfc_hba *phba = inode->i_private;
2135 struct lpfc_debug *debug;
2136 int size;
2137 int rc = -ENOMEM;
2138
2139 spin_lock_irq(&phba->hbalock);
2140 if (phba->ras_fwlog.state != ACTIVE) {
2141 spin_unlock_irq(&phba->hbalock);
2142 rc = -EINVAL;
2143 goto out;
2144 }
2145 spin_unlock_irq(&phba->hbalock);
2146 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2147 if (!debug)
2148 goto out;
2149
2150 size = LPFC_RAS_MIN_BUFF_POST_SIZE * phba->cfg_ras_fwlog_buffsize;
2151 debug->buffer = vmalloc(size);
2152 if (!debug->buffer)
2153 goto free_debug;
2154
2155 debug->len = lpfc_debugfs_ras_log_data(phba, debug->buffer, size);
2156 if (debug->len < 0) {
2157 rc = -EINVAL;
2158 goto free_buffer;
2159 }
2160 file->private_data = debug;
2161
2162 return 0;
2163
2164free_buffer:
2165 vfree(debug->buffer);
2166free_debug:
2167 kfree(debug);
2168out:
2169 return rc;
2170}
2171
James Smart5e5b5112019-01-28 11:14:22 -08002172/**
James Smart3621a712009-04-06 18:47:14 -04002173 * lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer
James Smarte59058c2008-08-24 21:49:00 -04002174 * @inode: The inode pointer that contains a vport pointer.
2175 * @file: The file pointer to attach the log output.
2176 *
2177 * Description:
2178 * This routine is the entry point for the debugfs open file operation. It gets
2179 * the vport from the i_private field in @inode, allocates the necessary buffer
2180 * for the log, fills the buffer from the in-memory log for this vport, and then
2181 * returns a pointer to that log in the private_data field in @file.
2182 *
2183 * Returns:
Geert Uytterhoeven79ce48d2015-05-21 14:11:33 +02002184 * This function returns zero if successful. On error it will return a negative
James Smarte59058c2008-08-24 21:49:00 -04002185 * error value.
2186 **/
James Smart78b2d852007-08-02 11:10:21 -04002187static int
James Smartc95d6c62008-01-11 01:53:23 -05002188lpfc_debugfs_dumpHBASlim_open(struct inode *inode, struct file *file)
James Smarta58cbd52007-08-02 11:09:43 -04002189{
2190 struct lpfc_hba *phba = inode->i_private;
2191 struct lpfc_debug *debug;
2192 int rc = -ENOMEM;
2193
2194 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2195 if (!debug)
2196 goto out;
2197
James Smarte59058c2008-08-24 21:49:00 -04002198 /* Round to page boundary */
James Smartc95d6c62008-01-11 01:53:23 -05002199 debug->buffer = kmalloc(LPFC_DUMPHBASLIM_SIZE, GFP_KERNEL);
James Smarta58cbd52007-08-02 11:09:43 -04002200 if (!debug->buffer) {
2201 kfree(debug);
2202 goto out;
2203 }
2204
James Smartc95d6c62008-01-11 01:53:23 -05002205 debug->len = lpfc_debugfs_dumpHBASlim_data(phba, debug->buffer,
2206 LPFC_DUMPHBASLIM_SIZE);
2207 file->private_data = debug;
2208
2209 rc = 0;
2210out:
2211 return rc;
2212}
2213
James Smarte59058c2008-08-24 21:49:00 -04002214/**
James Smart3621a712009-04-06 18:47:14 -04002215 * lpfc_debugfs_dumpHostSlim_open - Open the Dump Host SLIM debugfs buffer
James Smarte59058c2008-08-24 21:49:00 -04002216 * @inode: The inode pointer that contains a vport pointer.
2217 * @file: The file pointer to attach the log output.
2218 *
2219 * Description:
2220 * This routine is the entry point for the debugfs open file operation. It gets
2221 * the vport from the i_private field in @inode, allocates the necessary buffer
2222 * for the log, fills the buffer from the in-memory log for this vport, and then
2223 * returns a pointer to that log in the private_data field in @file.
2224 *
2225 * Returns:
Geert Uytterhoeven79ce48d2015-05-21 14:11:33 +02002226 * This function returns zero if successful. On error it will return a negative
James Smarte59058c2008-08-24 21:49:00 -04002227 * error value.
2228 **/
James Smartc95d6c62008-01-11 01:53:23 -05002229static int
2230lpfc_debugfs_dumpHostSlim_open(struct inode *inode, struct file *file)
2231{
2232 struct lpfc_hba *phba = inode->i_private;
2233 struct lpfc_debug *debug;
2234 int rc = -ENOMEM;
2235
2236 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2237 if (!debug)
2238 goto out;
2239
James Smarte59058c2008-08-24 21:49:00 -04002240 /* Round to page boundary */
James Smartc95d6c62008-01-11 01:53:23 -05002241 debug->buffer = kmalloc(LPFC_DUMPHOSTSLIM_SIZE, GFP_KERNEL);
2242 if (!debug->buffer) {
2243 kfree(debug);
2244 goto out;
2245 }
2246
2247 debug->len = lpfc_debugfs_dumpHostSlim_data(phba, debug->buffer,
2248 LPFC_DUMPHOSTSLIM_SIZE);
James Smarta58cbd52007-08-02 11:09:43 -04002249 file->private_data = debug;
2250
2251 rc = 0;
2252out:
2253 return rc;
2254}
2255
James Smartf9bb2da2011-10-10 21:34:11 -04002256static ssize_t
2257lpfc_debugfs_dif_err_read(struct file *file, char __user *buf,
2258 size_t nbytes, loff_t *ppos)
2259{
Al Virob5830432014-10-31 01:22:04 -04002260 struct dentry *dent = file->f_path.dentry;
James Smartf9bb2da2011-10-10 21:34:11 -04002261 struct lpfc_hba *phba = file->private_data;
James Smart9a6b09c2012-03-01 22:37:42 -05002262 char cbuf[32];
James Smart4ac9b222012-03-01 22:38:29 -05002263 uint64_t tmp = 0;
James Smartf9bb2da2011-10-10 21:34:11 -04002264 int cnt = 0;
2265
2266 if (dent == phba->debug_writeGuard)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07002267 cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wgrd_cnt);
James Smartf9bb2da2011-10-10 21:34:11 -04002268 else if (dent == phba->debug_writeApp)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07002269 cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wapp_cnt);
James Smartf9bb2da2011-10-10 21:34:11 -04002270 else if (dent == phba->debug_writeRef)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07002271 cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wref_cnt);
James Smartacd68592012-01-18 16:25:09 -05002272 else if (dent == phba->debug_readGuard)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07002273 cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rgrd_cnt);
James Smartf9bb2da2011-10-10 21:34:11 -04002274 else if (dent == phba->debug_readApp)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07002275 cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rapp_cnt);
James Smartf9bb2da2011-10-10 21:34:11 -04002276 else if (dent == phba->debug_readRef)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07002277 cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rref_cnt);
James Smart4ac9b222012-03-01 22:38:29 -05002278 else if (dent == phba->debug_InjErrNPortID)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07002279 cnt = scnprintf(cbuf, 32, "0x%06x\n",
2280 phba->lpfc_injerr_nportid);
James Smart4ac9b222012-03-01 22:38:29 -05002281 else if (dent == phba->debug_InjErrWWPN) {
2282 memcpy(&tmp, &phba->lpfc_injerr_wwpn, sizeof(struct lpfc_name));
2283 tmp = cpu_to_be64(tmp);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07002284 cnt = scnprintf(cbuf, 32, "0x%016llx\n", tmp);
James Smart4ac9b222012-03-01 22:38:29 -05002285 } else if (dent == phba->debug_InjErrLBA) {
2286 if (phba->lpfc_injerr_lba == (sector_t)(-1))
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07002287 cnt = scnprintf(cbuf, 32, "off\n");
James Smart9a6b09c2012-03-01 22:37:42 -05002288 else
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07002289 cnt = scnprintf(cbuf, 32, "0x%llx\n",
James Smart4ac9b222012-03-01 22:38:29 -05002290 (uint64_t) phba->lpfc_injerr_lba);
James Smart9a6b09c2012-03-01 22:37:42 -05002291 } else
James Smartf9bb2da2011-10-10 21:34:11 -04002292 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2293 "0547 Unknown debugfs error injection entry\n");
2294
2295 return simple_read_from_buffer(buf, nbytes, ppos, &cbuf, cnt);
2296}
2297
2298static ssize_t
2299lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
2300 size_t nbytes, loff_t *ppos)
2301{
Al Virob5830432014-10-31 01:22:04 -04002302 struct dentry *dent = file->f_path.dentry;
James Smartf9bb2da2011-10-10 21:34:11 -04002303 struct lpfc_hba *phba = file->private_data;
Alan0872774d2016-02-15 19:11:56 +00002304 char dstbuf[33];
James Smart4ac9b222012-03-01 22:38:29 -05002305 uint64_t tmp = 0;
James Smartf9bb2da2011-10-10 21:34:11 -04002306 int size;
2307
Alan0872774d2016-02-15 19:11:56 +00002308 memset(dstbuf, 0, 33);
James Smartf9bb2da2011-10-10 21:34:11 -04002309 size = (nbytes < 32) ? nbytes : 32;
2310 if (copy_from_user(dstbuf, buf, size))
2311 return 0;
2312
James Smart9a6b09c2012-03-01 22:37:42 -05002313 if (dent == phba->debug_InjErrLBA) {
2314 if ((buf[0] == 'o') && (buf[1] == 'f') && (buf[2] == 'f'))
James Smart4ac9b222012-03-01 22:38:29 -05002315 tmp = (uint64_t)(-1);
James Smart9a6b09c2012-03-01 22:37:42 -05002316 }
2317
James Smart4ac9b222012-03-01 22:38:29 -05002318 if ((tmp == 0) && (kstrtoull(dstbuf, 0, &tmp)))
James Smartf9bb2da2011-10-10 21:34:11 -04002319 return 0;
2320
2321 if (dent == phba->debug_writeGuard)
2322 phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp;
2323 else if (dent == phba->debug_writeApp)
2324 phba->lpfc_injerr_wapp_cnt = (uint32_t)tmp;
2325 else if (dent == phba->debug_writeRef)
2326 phba->lpfc_injerr_wref_cnt = (uint32_t)tmp;
James Smartacd68592012-01-18 16:25:09 -05002327 else if (dent == phba->debug_readGuard)
2328 phba->lpfc_injerr_rgrd_cnt = (uint32_t)tmp;
James Smartf9bb2da2011-10-10 21:34:11 -04002329 else if (dent == phba->debug_readApp)
2330 phba->lpfc_injerr_rapp_cnt = (uint32_t)tmp;
2331 else if (dent == phba->debug_readRef)
2332 phba->lpfc_injerr_rref_cnt = (uint32_t)tmp;
2333 else if (dent == phba->debug_InjErrLBA)
2334 phba->lpfc_injerr_lba = (sector_t)tmp;
James Smart4ac9b222012-03-01 22:38:29 -05002335 else if (dent == phba->debug_InjErrNPortID)
2336 phba->lpfc_injerr_nportid = (uint32_t)(tmp & Mask_DID);
2337 else if (dent == phba->debug_InjErrWWPN) {
2338 tmp = cpu_to_be64(tmp);
2339 memcpy(&phba->lpfc_injerr_wwpn, &tmp, sizeof(struct lpfc_name));
2340 } else
James Smartf9bb2da2011-10-10 21:34:11 -04002341 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2342 "0548 Unknown debugfs error injection entry\n");
2343
2344 return nbytes;
2345}
2346
2347static int
2348lpfc_debugfs_dif_err_release(struct inode *inode, struct file *file)
2349{
2350 return 0;
2351}
2352
James Smarte59058c2008-08-24 21:49:00 -04002353/**
James Smart3621a712009-04-06 18:47:14 -04002354 * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file
James Smarte59058c2008-08-24 21:49:00 -04002355 * @inode: The inode pointer that contains a vport pointer.
2356 * @file: The file pointer to attach the log output.
2357 *
2358 * Description:
2359 * This routine is the entry point for the debugfs open file operation. It gets
2360 * the vport from the i_private field in @inode, allocates the necessary buffer
2361 * for the log, fills the buffer from the in-memory log for this vport, and then
2362 * returns a pointer to that log in the private_data field in @file.
2363 *
2364 * Returns:
Geert Uytterhoeven79ce48d2015-05-21 14:11:33 +02002365 * This function returns zero if successful. On error it will return a negative
James Smarte59058c2008-08-24 21:49:00 -04002366 * error value.
2367 **/
James Smarta58cbd52007-08-02 11:09:43 -04002368static int
James Smart858c9f62007-06-17 19:56:39 -05002369lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file)
2370{
2371 struct lpfc_vport *vport = inode->i_private;
2372 struct lpfc_debug *debug;
2373 int rc = -ENOMEM;
2374
2375 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2376 if (!debug)
2377 goto out;
2378
James Smarte59058c2008-08-24 21:49:00 -04002379 /* Round to page boundary */
James Smart858c9f62007-06-17 19:56:39 -05002380 debug->buffer = kmalloc(LPFC_NODELIST_SIZE, GFP_KERNEL);
2381 if (!debug->buffer) {
2382 kfree(debug);
2383 goto out;
2384 }
2385
2386 debug->len = lpfc_debugfs_nodelist_data(vport, debug->buffer,
2387 LPFC_NODELIST_SIZE);
2388 file->private_data = debug;
2389
2390 rc = 0;
2391out:
2392 return rc;
2393}
2394
James Smarte59058c2008-08-24 21:49:00 -04002395/**
James Smart3621a712009-04-06 18:47:14 -04002396 * lpfc_debugfs_lseek - Seek through a debugfs file
James Smarte59058c2008-08-24 21:49:00 -04002397 * @file: The file pointer to seek through.
2398 * @off: The offset to seek to or the amount to seek by.
2399 * @whence: Indicates how to seek.
2400 *
2401 * Description:
2402 * This routine is the entry point for the debugfs lseek file operation. The
2403 * @whence parameter indicates whether @off is the offset to directly seek to,
2404 * or if it is a value to seek forward or reverse by. This function figures out
2405 * what the new offset of the debugfs file will be and assigns that value to the
2406 * f_pos field of @file.
2407 *
2408 * Returns:
2409 * This function returns the new offset if successful and returns a negative
2410 * error if unable to process the seek.
2411 **/
James Smart858c9f62007-06-17 19:56:39 -05002412static loff_t
2413lpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
2414{
Al Viro7233c772013-06-23 12:08:05 +04002415 struct lpfc_debug *debug = file->private_data;
2416 return fixed_size_llseek(file, off, whence, debug->len);
James Smart858c9f62007-06-17 19:56:39 -05002417}
2418
James Smarte59058c2008-08-24 21:49:00 -04002419/**
James Smart3621a712009-04-06 18:47:14 -04002420 * lpfc_debugfs_read - Read a debugfs file
James Smarte59058c2008-08-24 21:49:00 -04002421 * @file: The file pointer to read from.
2422 * @buf: The buffer to copy the data to.
2423 * @nbytes: The number of bytes to read.
2424 * @ppos: The position in the file to start reading from.
2425 *
2426 * Description:
2427 * This routine reads data from from the buffer indicated in the private_data
2428 * field of @file. It will start reading at @ppos and copy up to @nbytes of
2429 * data to @buf.
2430 *
2431 * Returns:
2432 * This function returns the amount of data that was read (this could be less
2433 * than @nbytes if the end of the file was reached) or a negative error value.
2434 **/
James Smart858c9f62007-06-17 19:56:39 -05002435static ssize_t
2436lpfc_debugfs_read(struct file *file, char __user *buf,
2437 size_t nbytes, loff_t *ppos)
2438{
2439 struct lpfc_debug *debug = file->private_data;
James Smart2a622bf2011-02-16 12:40:06 -05002440
James Smart858c9f62007-06-17 19:56:39 -05002441 return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer,
2442 debug->len);
2443}
2444
James Smarte59058c2008-08-24 21:49:00 -04002445/**
James Smart3621a712009-04-06 18:47:14 -04002446 * lpfc_debugfs_release - Release the buffer used to store debugfs file data
James Smarte59058c2008-08-24 21:49:00 -04002447 * @inode: The inode pointer that contains a vport pointer. (unused)
2448 * @file: The file pointer that contains the buffer to release.
2449 *
2450 * Description:
2451 * This routine frees the buffer that was allocated when the debugfs file was
2452 * opened.
2453 *
2454 * Returns:
2455 * This function returns zero.
2456 **/
James Smart858c9f62007-06-17 19:56:39 -05002457static int
2458lpfc_debugfs_release(struct inode *inode, struct file *file)
2459{
2460 struct lpfc_debug *debug = file->private_data;
2461
2462 kfree(debug->buffer);
2463 kfree(debug);
2464
2465 return 0;
2466}
2467
James Smartc4908502019-01-28 11:14:28 -08002468/**
2469 * lpfc_debugfs_multixripools_write - Clear multi-XRI pools statistics
2470 * @file: The file pointer to read from.
2471 * @buf: The buffer to copy the user data from.
2472 * @nbytes: The number of bytes to get.
2473 * @ppos: The position in the file to start reading from.
2474 *
2475 * Description:
2476 * This routine clears multi-XRI pools statistics when buf contains "clear".
2477 *
2478 * Return Value:
2479 * It returns the @nbytges passing in from debugfs user space when successful.
2480 * In case of error conditions, it returns proper error code back to the user
2481 * space.
2482 **/
2483static ssize_t
2484lpfc_debugfs_multixripools_write(struct file *file, const char __user *buf,
2485 size_t nbytes, loff_t *ppos)
2486{
2487 struct lpfc_debug *debug = file->private_data;
2488 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
2489 char mybuf[64];
2490 char *pbuf;
2491 u32 i;
2492 u32 hwq_count;
2493 struct lpfc_sli4_hdw_queue *qp;
2494 struct lpfc_multixri_pool *multixri_pool;
2495
2496 if (nbytes > 64)
2497 nbytes = 64;
2498
2499 /* Protect copy from user */
2500 if (!access_ok(buf, nbytes))
2501 return -EFAULT;
2502
2503 memset(mybuf, 0, sizeof(mybuf));
2504
2505 if (copy_from_user(mybuf, buf, nbytes))
2506 return -EFAULT;
2507 pbuf = &mybuf[0];
2508
2509 if ((strncmp(pbuf, "clear", strlen("clear"))) == 0) {
2510 hwq_count = phba->cfg_hdw_queue;
2511 for (i = 0; i < hwq_count; i++) {
2512 qp = &phba->sli4_hba.hdwq[i];
2513 multixri_pool = qp->p_multixri_pool;
2514 if (!multixri_pool)
2515 continue;
2516
2517 qp->empty_io_bufs = 0;
2518 multixri_pool->pbl_empty_count = 0;
2519#ifdef LPFC_MXP_STAT
2520 multixri_pool->above_limit_count = 0;
2521 multixri_pool->below_limit_count = 0;
2522 multixri_pool->stat_max_hwm = 0;
2523 multixri_pool->local_pbl_hit_count = 0;
2524 multixri_pool->other_pbl_hit_count = 0;
2525
2526 multixri_pool->stat_pbl_count = 0;
2527 multixri_pool->stat_pvt_count = 0;
2528 multixri_pool->stat_busy_count = 0;
2529 multixri_pool->stat_snapshot_taken = 0;
2530#endif
2531 }
2532 return strlen(pbuf);
2533 }
2534
2535 return -EINVAL;
2536}
James Smartbd2cdd52017-02-12 13:52:33 -08002537
2538static int
2539lpfc_debugfs_nvmestat_open(struct inode *inode, struct file *file)
2540{
2541 struct lpfc_vport *vport = inode->i_private;
2542 struct lpfc_debug *debug;
2543 int rc = -ENOMEM;
2544
2545 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2546 if (!debug)
2547 goto out;
2548
2549 /* Round to page boundary */
2550 debug->buffer = kmalloc(LPFC_NVMESTAT_SIZE, GFP_KERNEL);
2551 if (!debug->buffer) {
2552 kfree(debug);
2553 goto out;
2554 }
2555
2556 debug->len = lpfc_debugfs_nvmestat_data(vport, debug->buffer,
2557 LPFC_NVMESTAT_SIZE);
2558
2559 debug->i_private = inode->i_private;
2560 file->private_data = debug;
2561
2562 rc = 0;
2563out:
2564 return rc;
2565}
2566
James Smart2b65e182017-02-12 13:52:38 -08002567static ssize_t
2568lpfc_debugfs_nvmestat_write(struct file *file, const char __user *buf,
2569 size_t nbytes, loff_t *ppos)
2570{
2571 struct lpfc_debug *debug = file->private_data;
2572 struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private;
2573 struct lpfc_hba *phba = vport->phba;
2574 struct lpfc_nvmet_tgtport *tgtp;
2575 char mybuf[64];
2576 char *pbuf;
2577
2578 if (!phba->targetport)
2579 return -ENXIO;
2580
2581 if (nbytes > 64)
2582 nbytes = 64;
2583
James Smart2b65e182017-02-12 13:52:38 -08002584 memset(mybuf, 0, sizeof(mybuf));
2585
2586 if (copy_from_user(mybuf, buf, nbytes))
2587 return -EFAULT;
2588 pbuf = &mybuf[0];
2589
2590 tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
2591 if ((strncmp(pbuf, "reset", strlen("reset")) == 0) ||
2592 (strncmp(pbuf, "zero", strlen("zero")) == 0)) {
2593 atomic_set(&tgtp->rcv_ls_req_in, 0);
2594 atomic_set(&tgtp->rcv_ls_req_out, 0);
2595 atomic_set(&tgtp->rcv_ls_req_drop, 0);
2596 atomic_set(&tgtp->xmt_ls_abort, 0);
James Smart547077a2017-05-15 15:20:40 -07002597 atomic_set(&tgtp->xmt_ls_abort_cmpl, 0);
James Smart2b65e182017-02-12 13:52:38 -08002598 atomic_set(&tgtp->xmt_ls_rsp, 0);
2599 atomic_set(&tgtp->xmt_ls_drop, 0);
2600 atomic_set(&tgtp->xmt_ls_rsp_error, 0);
2601 atomic_set(&tgtp->xmt_ls_rsp_cmpl, 0);
2602
2603 atomic_set(&tgtp->rcv_fcp_cmd_in, 0);
2604 atomic_set(&tgtp->rcv_fcp_cmd_out, 0);
2605 atomic_set(&tgtp->rcv_fcp_cmd_drop, 0);
James Smart2b65e182017-02-12 13:52:38 -08002606 atomic_set(&tgtp->xmt_fcp_drop, 0);
2607 atomic_set(&tgtp->xmt_fcp_read_rsp, 0);
2608 atomic_set(&tgtp->xmt_fcp_read, 0);
2609 atomic_set(&tgtp->xmt_fcp_write, 0);
2610 atomic_set(&tgtp->xmt_fcp_rsp, 0);
James Smart547077a2017-05-15 15:20:40 -07002611 atomic_set(&tgtp->xmt_fcp_release, 0);
James Smart2b65e182017-02-12 13:52:38 -08002612 atomic_set(&tgtp->xmt_fcp_rsp_cmpl, 0);
2613 atomic_set(&tgtp->xmt_fcp_rsp_error, 0);
2614 atomic_set(&tgtp->xmt_fcp_rsp_drop, 0);
2615
James Smart547077a2017-05-15 15:20:40 -07002616 atomic_set(&tgtp->xmt_fcp_abort, 0);
2617 atomic_set(&tgtp->xmt_fcp_abort_cmpl, 0);
2618 atomic_set(&tgtp->xmt_abort_sol, 0);
2619 atomic_set(&tgtp->xmt_abort_unsol, 0);
James Smart2b65e182017-02-12 13:52:38 -08002620 atomic_set(&tgtp->xmt_abort_rsp, 0);
2621 atomic_set(&tgtp->xmt_abort_rsp_error, 0);
James Smart2b65e182017-02-12 13:52:38 -08002622 }
2623 return nbytes;
2624}
2625
James Smartbd2cdd52017-02-12 13:52:33 -08002626static int
James Smart4c47efc2019-01-28 11:14:25 -08002627lpfc_debugfs_scsistat_open(struct inode *inode, struct file *file)
2628{
2629 struct lpfc_vport *vport = inode->i_private;
2630 struct lpfc_debug *debug;
2631 int rc = -ENOMEM;
2632
2633 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2634 if (!debug)
2635 goto out;
2636
2637 /* Round to page boundary */
2638 debug->buffer = kzalloc(LPFC_SCSISTAT_SIZE, GFP_KERNEL);
2639 if (!debug->buffer) {
2640 kfree(debug);
2641 goto out;
2642 }
2643
2644 debug->len = lpfc_debugfs_scsistat_data(vport, debug->buffer,
2645 LPFC_SCSISTAT_SIZE);
2646
2647 debug->i_private = inode->i_private;
2648 file->private_data = debug;
2649
2650 rc = 0;
2651out:
2652 return rc;
2653}
2654
2655static ssize_t
2656lpfc_debugfs_scsistat_write(struct file *file, const char __user *buf,
2657 size_t nbytes, loff_t *ppos)
2658{
2659 struct lpfc_debug *debug = file->private_data;
2660 struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private;
2661 struct lpfc_hba *phba = vport->phba;
2662 char mybuf[6] = {0};
2663 int i;
2664
2665 /* Protect copy from user */
2666 if (!access_ok(buf, nbytes))
2667 return -EFAULT;
2668
2669 if (copy_from_user(mybuf, buf, (nbytes >= sizeof(mybuf)) ?
2670 (sizeof(mybuf) - 1) : nbytes))
2671 return -EFAULT;
2672
2673 if ((strncmp(&mybuf[0], "reset", strlen("reset")) == 0) ||
2674 (strncmp(&mybuf[0], "zero", strlen("zero")) == 0)) {
2675 for (i = 0; i < phba->cfg_hdw_queue; i++) {
2676 memset(&phba->sli4_hba.hdwq[i].scsi_cstat, 0,
2677 sizeof(phba->sli4_hba.hdwq[i].scsi_cstat));
2678 }
2679 }
2680
2681 return nbytes;
2682}
2683
2684static int
James Smartbd2cdd52017-02-12 13:52:33 -08002685lpfc_debugfs_nvmektime_open(struct inode *inode, struct file *file)
2686{
2687 struct lpfc_vport *vport = inode->i_private;
2688 struct lpfc_debug *debug;
2689 int rc = -ENOMEM;
2690
2691 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2692 if (!debug)
2693 goto out;
2694
2695 /* Round to page boundary */
2696 debug->buffer = kmalloc(LPFC_NVMEKTIME_SIZE, GFP_KERNEL);
2697 if (!debug->buffer) {
2698 kfree(debug);
2699 goto out;
2700 }
2701
2702 debug->len = lpfc_debugfs_nvmektime_data(vport, debug->buffer,
2703 LPFC_NVMEKTIME_SIZE);
2704
2705 debug->i_private = inode->i_private;
2706 file->private_data = debug;
2707
2708 rc = 0;
2709out:
2710 return rc;
2711}
2712
2713static ssize_t
2714lpfc_debugfs_nvmektime_write(struct file *file, const char __user *buf,
2715 size_t nbytes, loff_t *ppos)
2716{
2717 struct lpfc_debug *debug = file->private_data;
2718 struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private;
2719 struct lpfc_hba *phba = vport->phba;
2720 char mybuf[64];
2721 char *pbuf;
2722
2723 if (nbytes > 64)
2724 nbytes = 64;
2725
James Smartbd2cdd52017-02-12 13:52:33 -08002726 memset(mybuf, 0, sizeof(mybuf));
2727
2728 if (copy_from_user(mybuf, buf, nbytes))
2729 return -EFAULT;
2730 pbuf = &mybuf[0];
2731
2732 if ((strncmp(pbuf, "on", sizeof("on") - 1) == 0)) {
2733 phba->ktime_data_samples = 0;
2734 phba->ktime_status_samples = 0;
2735 phba->ktime_seg1_total = 0;
2736 phba->ktime_seg1_max = 0;
2737 phba->ktime_seg1_min = 0xffffffff;
2738 phba->ktime_seg2_total = 0;
2739 phba->ktime_seg2_max = 0;
2740 phba->ktime_seg2_min = 0xffffffff;
2741 phba->ktime_seg3_total = 0;
2742 phba->ktime_seg3_max = 0;
2743 phba->ktime_seg3_min = 0xffffffff;
2744 phba->ktime_seg4_total = 0;
2745 phba->ktime_seg4_max = 0;
2746 phba->ktime_seg4_min = 0xffffffff;
2747 phba->ktime_seg5_total = 0;
2748 phba->ktime_seg5_max = 0;
2749 phba->ktime_seg5_min = 0xffffffff;
2750 phba->ktime_seg6_total = 0;
2751 phba->ktime_seg6_max = 0;
2752 phba->ktime_seg6_min = 0xffffffff;
2753 phba->ktime_seg7_total = 0;
2754 phba->ktime_seg7_max = 0;
2755 phba->ktime_seg7_min = 0xffffffff;
2756 phba->ktime_seg8_total = 0;
2757 phba->ktime_seg8_max = 0;
2758 phba->ktime_seg8_min = 0xffffffff;
2759 phba->ktime_seg9_total = 0;
2760 phba->ktime_seg9_max = 0;
2761 phba->ktime_seg9_min = 0xffffffff;
2762 phba->ktime_seg10_total = 0;
2763 phba->ktime_seg10_max = 0;
2764 phba->ktime_seg10_min = 0xffffffff;
2765
2766 phba->ktime_on = 1;
2767 return strlen(pbuf);
2768 } else if ((strncmp(pbuf, "off",
2769 sizeof("off") - 1) == 0)) {
2770 phba->ktime_on = 0;
2771 return strlen(pbuf);
2772 } else if ((strncmp(pbuf, "zero",
2773 sizeof("zero") - 1) == 0)) {
2774 phba->ktime_data_samples = 0;
2775 phba->ktime_status_samples = 0;
2776 phba->ktime_seg1_total = 0;
2777 phba->ktime_seg1_max = 0;
2778 phba->ktime_seg1_min = 0xffffffff;
2779 phba->ktime_seg2_total = 0;
2780 phba->ktime_seg2_max = 0;
2781 phba->ktime_seg2_min = 0xffffffff;
2782 phba->ktime_seg3_total = 0;
2783 phba->ktime_seg3_max = 0;
2784 phba->ktime_seg3_min = 0xffffffff;
2785 phba->ktime_seg4_total = 0;
2786 phba->ktime_seg4_max = 0;
2787 phba->ktime_seg4_min = 0xffffffff;
2788 phba->ktime_seg5_total = 0;
2789 phba->ktime_seg5_max = 0;
2790 phba->ktime_seg5_min = 0xffffffff;
2791 phba->ktime_seg6_total = 0;
2792 phba->ktime_seg6_max = 0;
2793 phba->ktime_seg6_min = 0xffffffff;
2794 phba->ktime_seg7_total = 0;
2795 phba->ktime_seg7_max = 0;
2796 phba->ktime_seg7_min = 0xffffffff;
2797 phba->ktime_seg8_total = 0;
2798 phba->ktime_seg8_max = 0;
2799 phba->ktime_seg8_min = 0xffffffff;
2800 phba->ktime_seg9_total = 0;
2801 phba->ktime_seg9_max = 0;
2802 phba->ktime_seg9_min = 0xffffffff;
2803 phba->ktime_seg10_total = 0;
2804 phba->ktime_seg10_max = 0;
2805 phba->ktime_seg10_min = 0xffffffff;
2806 return strlen(pbuf);
2807 }
2808 return -EINVAL;
2809}
2810
2811static int
2812lpfc_debugfs_nvmeio_trc_open(struct inode *inode, struct file *file)
2813{
2814 struct lpfc_hba *phba = inode->i_private;
2815 struct lpfc_debug *debug;
2816 int rc = -ENOMEM;
2817
2818 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2819 if (!debug)
2820 goto out;
2821
2822 /* Round to page boundary */
2823 debug->buffer = kmalloc(LPFC_NVMEIO_TRC_SIZE, GFP_KERNEL);
2824 if (!debug->buffer) {
2825 kfree(debug);
2826 goto out;
2827 }
2828
2829 debug->len = lpfc_debugfs_nvmeio_trc_data(phba, debug->buffer,
2830 LPFC_NVMEIO_TRC_SIZE);
2831
2832 debug->i_private = inode->i_private;
2833 file->private_data = debug;
2834
2835 rc = 0;
2836out:
2837 return rc;
2838}
2839
2840static ssize_t
2841lpfc_debugfs_nvmeio_trc_write(struct file *file, const char __user *buf,
2842 size_t nbytes, loff_t *ppos)
2843{
2844 struct lpfc_debug *debug = file->private_data;
2845 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
2846 int i;
2847 unsigned long sz;
2848 char mybuf[64];
2849 char *pbuf;
2850
2851 if (nbytes > 64)
2852 nbytes = 64;
2853
James Smartbd2cdd52017-02-12 13:52:33 -08002854 memset(mybuf, 0, sizeof(mybuf));
2855
2856 if (copy_from_user(mybuf, buf, nbytes))
2857 return -EFAULT;
2858 pbuf = &mybuf[0];
2859
2860 if ((strncmp(pbuf, "off", sizeof("off") - 1) == 0)) {
2861 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2862 "0570 nvmeio_trc_off\n");
2863 phba->nvmeio_trc_output_idx = 0;
2864 phba->nvmeio_trc_on = 0;
2865 return strlen(pbuf);
2866 } else if ((strncmp(pbuf, "on", sizeof("on") - 1) == 0)) {
2867 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2868 "0571 nvmeio_trc_on\n");
2869 phba->nvmeio_trc_output_idx = 0;
2870 phba->nvmeio_trc_on = 1;
2871 return strlen(pbuf);
2872 }
2873
2874 /* We must be off to allocate the trace buffer */
2875 if (phba->nvmeio_trc_on != 0)
2876 return -EINVAL;
2877
2878 /* If not on or off, the parameter is the trace buffer size */
2879 i = kstrtoul(pbuf, 0, &sz);
2880 if (i)
2881 return -EINVAL;
2882 phba->nvmeio_trc_size = (uint32_t)sz;
2883
2884 /* It must be a power of 2 - round down */
2885 i = 0;
2886 while (sz > 1) {
2887 sz = sz >> 1;
2888 i++;
2889 }
2890 sz = (1 << i);
2891 if (phba->nvmeio_trc_size != sz)
2892 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2893 "0572 nvmeio_trc_size changed to %ld\n",
2894 sz);
2895 phba->nvmeio_trc_size = (uint32_t)sz;
2896
2897 /* If one previously exists, free it */
2898 kfree(phba->nvmeio_trc);
2899
2900 /* Allocate new trace buffer and initialize */
Vasyl Gomonovych1c356ec2017-10-11 21:42:41 +02002901 phba->nvmeio_trc = kzalloc((sizeof(struct lpfc_debugfs_nvmeio_trc) *
James Smartbd2cdd52017-02-12 13:52:33 -08002902 sz), GFP_KERNEL);
2903 if (!phba->nvmeio_trc) {
2904 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2905 "0573 Cannot create debugfs "
2906 "nvmeio_trc buffer\n");
2907 return -ENOMEM;
2908 }
James Smartbd2cdd52017-02-12 13:52:33 -08002909 atomic_set(&phba->nvmeio_trc_cnt, 0);
2910 phba->nvmeio_trc_on = 0;
2911 phba->nvmeio_trc_output_idx = 0;
2912
2913 return strlen(pbuf);
2914}
2915
2916static int
2917lpfc_debugfs_cpucheck_open(struct inode *inode, struct file *file)
2918{
2919 struct lpfc_vport *vport = inode->i_private;
2920 struct lpfc_debug *debug;
2921 int rc = -ENOMEM;
2922
2923 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2924 if (!debug)
2925 goto out;
2926
2927 /* Round to page boundary */
2928 debug->buffer = kmalloc(LPFC_CPUCHECK_SIZE, GFP_KERNEL);
2929 if (!debug->buffer) {
2930 kfree(debug);
2931 goto out;
2932 }
2933
2934 debug->len = lpfc_debugfs_cpucheck_data(vport, debug->buffer,
James Smart6a828b02019-01-28 11:14:31 -08002935 LPFC_CPUCHECK_SIZE);
James Smartbd2cdd52017-02-12 13:52:33 -08002936
2937 debug->i_private = inode->i_private;
2938 file->private_data = debug;
2939
2940 rc = 0;
2941out:
2942 return rc;
2943}
2944
2945static ssize_t
2946lpfc_debugfs_cpucheck_write(struct file *file, const char __user *buf,
2947 size_t nbytes, loff_t *ppos)
2948{
2949 struct lpfc_debug *debug = file->private_data;
2950 struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private;
2951 struct lpfc_hba *phba = vport->phba;
James Smart63df6d62019-01-28 11:14:24 -08002952 struct lpfc_sli4_hdw_queue *qp;
James Smartbd2cdd52017-02-12 13:52:33 -08002953 char mybuf[64];
2954 char *pbuf;
James Smart63df6d62019-01-28 11:14:24 -08002955 int i, j;
James Smartbd2cdd52017-02-12 13:52:33 -08002956
2957 if (nbytes > 64)
2958 nbytes = 64;
2959
James Smartbd2cdd52017-02-12 13:52:33 -08002960 memset(mybuf, 0, sizeof(mybuf));
2961
2962 if (copy_from_user(mybuf, buf, nbytes))
2963 return -EFAULT;
2964 pbuf = &mybuf[0];
2965
2966 if ((strncmp(pbuf, "on", sizeof("on") - 1) == 0)) {
James Smart2b65e182017-02-12 13:52:38 -08002967 if (phba->nvmet_support)
2968 phba->cpucheck_on |= LPFC_CHECK_NVMET_IO;
2969 else
James Smart6a828b02019-01-28 11:14:31 -08002970 phba->cpucheck_on |= (LPFC_CHECK_NVME_IO |
2971 LPFC_CHECK_SCSI_IO);
2972 return strlen(pbuf);
2973 } else if ((strncmp(pbuf, "nvme_on", sizeof("nvme_on") - 1) == 0)) {
2974 if (phba->nvmet_support)
2975 phba->cpucheck_on |= LPFC_CHECK_NVMET_IO;
2976 else
James Smart2b65e182017-02-12 13:52:38 -08002977 phba->cpucheck_on |= LPFC_CHECK_NVME_IO;
James Smartbd2cdd52017-02-12 13:52:33 -08002978 return strlen(pbuf);
James Smart6a828b02019-01-28 11:14:31 -08002979 } else if ((strncmp(pbuf, "scsi_on", sizeof("scsi_on") - 1) == 0)) {
2980 phba->cpucheck_on |= LPFC_CHECK_SCSI_IO;
2981 return strlen(pbuf);
James Smartbd2cdd52017-02-12 13:52:33 -08002982 } else if ((strncmp(pbuf, "rcv",
2983 sizeof("rcv") - 1) == 0)) {
James Smartf358dd02017-02-12 13:52:34 -08002984 if (phba->nvmet_support)
2985 phba->cpucheck_on |= LPFC_CHECK_NVMET_RCV;
2986 else
2987 return -EINVAL;
2988 return strlen(pbuf);
James Smartbd2cdd52017-02-12 13:52:33 -08002989 } else if ((strncmp(pbuf, "off",
2990 sizeof("off") - 1) == 0)) {
2991 phba->cpucheck_on = LPFC_CHECK_OFF;
2992 return strlen(pbuf);
2993 } else if ((strncmp(pbuf, "zero",
2994 sizeof("zero") - 1) == 0)) {
James Smart63df6d62019-01-28 11:14:24 -08002995 for (i = 0; i < phba->cfg_hdw_queue; i++) {
2996 qp = &phba->sli4_hba.hdwq[i];
2997
2998 for (j = 0; j < LPFC_CHECK_CPU_CNT; j++) {
2999 qp->cpucheck_rcv_io[j] = 0;
3000 qp->cpucheck_xmt_io[j] = 0;
3001 qp->cpucheck_cmpl_io[j] = 0;
3002 }
James Smartbd2cdd52017-02-12 13:52:33 -08003003 }
3004 return strlen(pbuf);
3005 }
3006 return -EINVAL;
3007}
3008
James Smart2a622bf2011-02-16 12:40:06 -05003009/*
James Smart86a80842011-04-16 11:03:04 -04003010 * ---------------------------------
James Smart2a622bf2011-02-16 12:40:06 -05003011 * iDiag debugfs file access methods
James Smart86a80842011-04-16 11:03:04 -04003012 * ---------------------------------
James Smart2a622bf2011-02-16 12:40:06 -05003013 *
James Smart86a80842011-04-16 11:03:04 -04003014 * All access methods are through the proper SLI4 PCI function's debugfs
3015 * iDiag directory:
James Smart2a622bf2011-02-16 12:40:06 -05003016 *
James Smart86a80842011-04-16 11:03:04 -04003017 * /sys/kernel/debug/lpfc/fn<#>/iDiag
James Smart2a622bf2011-02-16 12:40:06 -05003018 */
3019
3020/**
3021 * lpfc_idiag_cmd_get - Get and parse idiag debugfs comands from user space
3022 * @buf: The pointer to the user space buffer.
3023 * @nbytes: The number of bytes in the user space buffer.
3024 * @idiag_cmd: pointer to the idiag command struct.
3025 *
3026 * This routine reads data from debugfs user space buffer and parses the
3027 * buffer for getting the idiag command and arguments. The while space in
3028 * between the set of data is used as the parsing separator.
3029 *
3030 * This routine returns 0 when successful, it returns proper error code
3031 * back to the user space in error conditions.
3032 */
3033static int lpfc_idiag_cmd_get(const char __user *buf, size_t nbytes,
3034 struct lpfc_idiag_cmd *idiag_cmd)
3035{
3036 char mybuf[64];
3037 char *pbuf, *step_str;
Stephen Boydb11d48e2011-05-12 16:50:06 -07003038 int i;
3039 size_t bsize;
James Smart2a622bf2011-02-16 12:40:06 -05003040
James Smart2a622bf2011-02-16 12:40:06 -05003041 memset(mybuf, 0, sizeof(mybuf));
3042 memset(idiag_cmd, 0, sizeof(*idiag_cmd));
3043 bsize = min(nbytes, (sizeof(mybuf)-1));
3044
3045 if (copy_from_user(mybuf, buf, bsize))
3046 return -EFAULT;
3047 pbuf = &mybuf[0];
3048 step_str = strsep(&pbuf, "\t ");
3049
3050 /* The opcode must present */
3051 if (!step_str)
3052 return -EINVAL;
3053
3054 idiag_cmd->opcode = simple_strtol(step_str, NULL, 0);
3055 if (idiag_cmd->opcode == 0)
3056 return -EINVAL;
3057
3058 for (i = 0; i < LPFC_IDIAG_CMD_DATA_SIZE; i++) {
3059 step_str = strsep(&pbuf, "\t ");
3060 if (!step_str)
James Smart86a80842011-04-16 11:03:04 -04003061 return i;
James Smart2a622bf2011-02-16 12:40:06 -05003062 idiag_cmd->data[i] = simple_strtol(step_str, NULL, 0);
3063 }
James Smart86a80842011-04-16 11:03:04 -04003064 return i;
James Smart2a622bf2011-02-16 12:40:06 -05003065}
3066
3067/**
3068 * lpfc_idiag_open - idiag open debugfs
3069 * @inode: The inode pointer that contains a pointer to phba.
3070 * @file: The file pointer to attach the file operation.
3071 *
3072 * Description:
3073 * This routine is the entry point for the debugfs open file operation. It
3074 * gets the reference to phba from the i_private field in @inode, it then
3075 * allocates buffer for the file operation, performs the necessary PCI config
3076 * space read into the allocated buffer according to the idiag user command
3077 * setup, and then returns a pointer to buffer in the private_data field in
3078 * @file.
3079 *
3080 * Returns:
3081 * This function returns zero if successful. On error it will return an
3082 * negative error value.
3083 **/
3084static int
3085lpfc_idiag_open(struct inode *inode, struct file *file)
3086{
3087 struct lpfc_debug *debug;
3088
3089 debug = kmalloc(sizeof(*debug), GFP_KERNEL);
3090 if (!debug)
3091 return -ENOMEM;
3092
3093 debug->i_private = inode->i_private;
3094 debug->buffer = NULL;
3095 file->private_data = debug;
3096
3097 return 0;
3098}
3099
3100/**
3101 * lpfc_idiag_release - Release idiag access file operation
3102 * @inode: The inode pointer that contains a vport pointer. (unused)
3103 * @file: The file pointer that contains the buffer to release.
3104 *
3105 * Description:
3106 * This routine is the generic release routine for the idiag access file
3107 * operation, it frees the buffer that was allocated when the debugfs file
3108 * was opened.
3109 *
3110 * Returns:
3111 * This function returns zero.
3112 **/
3113static int
3114lpfc_idiag_release(struct inode *inode, struct file *file)
3115{
3116 struct lpfc_debug *debug = file->private_data;
3117
3118 /* Free the buffers to the file operation */
3119 kfree(debug->buffer);
3120 kfree(debug);
3121
3122 return 0;
3123}
3124
3125/**
3126 * lpfc_idiag_cmd_release - Release idiag cmd access file operation
3127 * @inode: The inode pointer that contains a vport pointer. (unused)
3128 * @file: The file pointer that contains the buffer to release.
3129 *
3130 * Description:
3131 * This routine frees the buffer that was allocated when the debugfs file
3132 * was opened. It also reset the fields in the idiag command struct in the
James Smart86a80842011-04-16 11:03:04 -04003133 * case of command for write operation.
James Smart2a622bf2011-02-16 12:40:06 -05003134 *
3135 * Returns:
3136 * This function returns zero.
3137 **/
3138static int
3139lpfc_idiag_cmd_release(struct inode *inode, struct file *file)
3140{
3141 struct lpfc_debug *debug = file->private_data;
3142
James Smart86a80842011-04-16 11:03:04 -04003143 if (debug->op == LPFC_IDIAG_OP_WR) {
3144 switch (idiag.cmd.opcode) {
3145 case LPFC_IDIAG_CMD_PCICFG_WR:
3146 case LPFC_IDIAG_CMD_PCICFG_ST:
3147 case LPFC_IDIAG_CMD_PCICFG_CL:
3148 case LPFC_IDIAG_CMD_QUEACC_WR:
3149 case LPFC_IDIAG_CMD_QUEACC_ST:
3150 case LPFC_IDIAG_CMD_QUEACC_CL:
James Smart2a622bf2011-02-16 12:40:06 -05003151 memset(&idiag, 0, sizeof(idiag));
James Smart86a80842011-04-16 11:03:04 -04003152 break;
3153 default:
3154 break;
3155 }
3156 }
James Smart2a622bf2011-02-16 12:40:06 -05003157
3158 /* Free the buffers to the file operation */
3159 kfree(debug->buffer);
3160 kfree(debug);
3161
3162 return 0;
3163}
3164
3165/**
3166 * lpfc_idiag_pcicfg_read - idiag debugfs read pcicfg
3167 * @file: The file pointer to read from.
3168 * @buf: The buffer to copy the data to.
3169 * @nbytes: The number of bytes to read.
3170 * @ppos: The position in the file to start reading from.
3171 *
3172 * Description:
3173 * This routine reads data from the @phba pci config space according to the
3174 * idiag command, and copies to user @buf. Depending on the PCI config space
3175 * read command setup, it does either a single register read of a byte
3176 * (8 bits), a word (16 bits), or a dword (32 bits) or browsing through all
3177 * registers from the 4K extended PCI config space.
3178 *
3179 * Returns:
3180 * This function returns the amount of data that was read (this could be less
3181 * than @nbytes if the end of the file was reached) or a negative error value.
3182 **/
3183static ssize_t
3184lpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes,
3185 loff_t *ppos)
3186{
3187 struct lpfc_debug *debug = file->private_data;
3188 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
3189 int offset_label, offset, len = 0, index = LPFC_PCI_CFG_RD_SIZE;
3190 int where, count;
3191 char *pbuffer;
3192 struct pci_dev *pdev;
3193 uint32_t u32val;
3194 uint16_t u16val;
3195 uint8_t u8val;
3196
3197 pdev = phba->pcidev;
3198 if (!pdev)
3199 return 0;
3200
3201 /* This is a user read operation */
3202 debug->op = LPFC_IDIAG_OP_RD;
3203
3204 if (!debug->buffer)
3205 debug->buffer = kmalloc(LPFC_PCI_CFG_SIZE, GFP_KERNEL);
3206 if (!debug->buffer)
3207 return 0;
3208 pbuffer = debug->buffer;
3209
3210 if (*ppos)
3211 return 0;
3212
3213 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) {
James Smartb76f2dc2011-07-22 18:37:42 -04003214 where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
3215 count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
James Smart2a622bf2011-02-16 12:40:06 -05003216 } else
3217 return 0;
3218
3219 /* Read single PCI config space register */
3220 switch (count) {
3221 case SIZE_U8: /* byte (8 bits) */
3222 pci_read_config_byte(pdev, where, &u8val);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003223 len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
James Smart2a622bf2011-02-16 12:40:06 -05003224 "%03x: %02x\n", where, u8val);
3225 break;
3226 case SIZE_U16: /* word (16 bits) */
3227 pci_read_config_word(pdev, where, &u16val);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003228 len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
James Smart2a622bf2011-02-16 12:40:06 -05003229 "%03x: %04x\n", where, u16val);
3230 break;
3231 case SIZE_U32: /* double word (32 bits) */
3232 pci_read_config_dword(pdev, where, &u32val);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003233 len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
James Smart2a622bf2011-02-16 12:40:06 -05003234 "%03x: %08x\n", where, u32val);
3235 break;
James Smart86a80842011-04-16 11:03:04 -04003236 case LPFC_PCI_CFG_BROWSE: /* browse all */
James Smart2a622bf2011-02-16 12:40:06 -05003237 goto pcicfg_browse;
3238 break;
3239 default:
3240 /* illegal count */
3241 len = 0;
3242 break;
3243 }
3244 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
3245
3246pcicfg_browse:
3247
3248 /* Browse all PCI config space registers */
3249 offset_label = idiag.offset.last_rd;
3250 offset = offset_label;
3251
3252 /* Read PCI config space */
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003253 len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
James Smart2a622bf2011-02-16 12:40:06 -05003254 "%03x: ", offset_label);
3255 while (index > 0) {
3256 pci_read_config_dword(pdev, offset, &u32val);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003257 len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
James Smart2a622bf2011-02-16 12:40:06 -05003258 "%08x ", u32val);
3259 offset += sizeof(uint32_t);
James Smartb76f2dc2011-07-22 18:37:42 -04003260 if (offset >= LPFC_PCI_CFG_SIZE) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003261 len += scnprintf(pbuffer+len,
James Smartb76f2dc2011-07-22 18:37:42 -04003262 LPFC_PCI_CFG_SIZE-len, "\n");
3263 break;
3264 }
James Smart2a622bf2011-02-16 12:40:06 -05003265 index -= sizeof(uint32_t);
3266 if (!index)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003267 len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
James Smart2a622bf2011-02-16 12:40:06 -05003268 "\n");
3269 else if (!(index % (8 * sizeof(uint32_t)))) {
3270 offset_label += (8 * sizeof(uint32_t));
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003271 len += scnprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
James Smart2a622bf2011-02-16 12:40:06 -05003272 "\n%03x: ", offset_label);
3273 }
3274 }
3275
3276 /* Set up the offset for next portion of pci cfg read */
James Smartb76f2dc2011-07-22 18:37:42 -04003277 if (index == 0) {
3278 idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE;
3279 if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE)
3280 idiag.offset.last_rd = 0;
3281 } else
James Smart2a622bf2011-02-16 12:40:06 -05003282 idiag.offset.last_rd = 0;
3283
3284 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
3285}
3286
3287/**
3288 * lpfc_idiag_pcicfg_write - Syntax check and set up idiag pcicfg commands
3289 * @file: The file pointer to read from.
3290 * @buf: The buffer to copy the user data from.
3291 * @nbytes: The number of bytes to get.
3292 * @ppos: The position in the file to start reading from.
3293 *
3294 * This routine get the debugfs idiag command struct from user space and
3295 * then perform the syntax check for PCI config space read or write command
3296 * accordingly. In the case of PCI config space read command, it sets up
3297 * the command in the idiag command struct for the debugfs read operation.
3298 * In the case of PCI config space write operation, it executes the write
3299 * operation into the PCI config space accordingly.
3300 *
3301 * It returns the @nbytges passing in from debugfs user space when successful.
3302 * In case of error conditions, it returns proper error code back to the user
3303 * space.
3304 */
3305static ssize_t
3306lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf,
3307 size_t nbytes, loff_t *ppos)
3308{
3309 struct lpfc_debug *debug = file->private_data;
3310 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
3311 uint32_t where, value, count;
3312 uint32_t u32val;
3313 uint16_t u16val;
3314 uint8_t u8val;
3315 struct pci_dev *pdev;
3316 int rc;
3317
3318 pdev = phba->pcidev;
3319 if (!pdev)
3320 return -EFAULT;
3321
3322 /* This is a user write operation */
3323 debug->op = LPFC_IDIAG_OP_WR;
3324
3325 rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
James Smart86a80842011-04-16 11:03:04 -04003326 if (rc < 0)
James Smart2a622bf2011-02-16 12:40:06 -05003327 return rc;
3328
3329 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) {
James Smart86a80842011-04-16 11:03:04 -04003330 /* Sanity check on PCI config read command line arguments */
3331 if (rc != LPFC_PCI_CFG_RD_CMD_ARG)
3332 goto error_out;
James Smart2a622bf2011-02-16 12:40:06 -05003333 /* Read command from PCI config space, set up command fields */
James Smartb76f2dc2011-07-22 18:37:42 -04003334 where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
3335 count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
James Smart86a80842011-04-16 11:03:04 -04003336 if (count == LPFC_PCI_CFG_BROWSE) {
3337 if (where % sizeof(uint32_t))
James Smart2a622bf2011-02-16 12:40:06 -05003338 goto error_out;
James Smart86a80842011-04-16 11:03:04 -04003339 /* Starting offset to browse */
3340 idiag.offset.last_rd = where;
James Smart2a622bf2011-02-16 12:40:06 -05003341 } else if ((count != sizeof(uint8_t)) &&
3342 (count != sizeof(uint16_t)) &&
3343 (count != sizeof(uint32_t)))
3344 goto error_out;
3345 if (count == sizeof(uint8_t)) {
3346 if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t))
3347 goto error_out;
3348 if (where % sizeof(uint8_t))
3349 goto error_out;
3350 }
3351 if (count == sizeof(uint16_t)) {
3352 if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t))
3353 goto error_out;
3354 if (where % sizeof(uint16_t))
3355 goto error_out;
3356 }
3357 if (count == sizeof(uint32_t)) {
3358 if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t))
3359 goto error_out;
3360 if (where % sizeof(uint32_t))
3361 goto error_out;
3362 }
3363 } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR ||
3364 idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST ||
3365 idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
James Smart86a80842011-04-16 11:03:04 -04003366 /* Sanity check on PCI config write command line arguments */
3367 if (rc != LPFC_PCI_CFG_WR_CMD_ARG)
3368 goto error_out;
James Smart2a622bf2011-02-16 12:40:06 -05003369 /* Write command to PCI config space, read-modify-write */
James Smartb76f2dc2011-07-22 18:37:42 -04003370 where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
3371 count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
3372 value = idiag.cmd.data[IDIAG_PCICFG_VALUE_INDX];
James Smart2a622bf2011-02-16 12:40:06 -05003373 /* Sanity checks */
3374 if ((count != sizeof(uint8_t)) &&
3375 (count != sizeof(uint16_t)) &&
3376 (count != sizeof(uint32_t)))
3377 goto error_out;
3378 if (count == sizeof(uint8_t)) {
3379 if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t))
3380 goto error_out;
3381 if (where % sizeof(uint8_t))
3382 goto error_out;
3383 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
3384 pci_write_config_byte(pdev, where,
3385 (uint8_t)value);
3386 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
3387 rc = pci_read_config_byte(pdev, where, &u8val);
3388 if (!rc) {
3389 u8val |= (uint8_t)value;
3390 pci_write_config_byte(pdev, where,
3391 u8val);
3392 }
3393 }
3394 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
3395 rc = pci_read_config_byte(pdev, where, &u8val);
3396 if (!rc) {
3397 u8val &= (uint8_t)(~value);
3398 pci_write_config_byte(pdev, where,
3399 u8val);
3400 }
3401 }
3402 }
3403 if (count == sizeof(uint16_t)) {
3404 if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t))
3405 goto error_out;
3406 if (where % sizeof(uint16_t))
3407 goto error_out;
3408 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
3409 pci_write_config_word(pdev, where,
3410 (uint16_t)value);
3411 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
3412 rc = pci_read_config_word(pdev, where, &u16val);
3413 if (!rc) {
3414 u16val |= (uint16_t)value;
3415 pci_write_config_word(pdev, where,
3416 u16val);
3417 }
3418 }
3419 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
3420 rc = pci_read_config_word(pdev, where, &u16val);
3421 if (!rc) {
3422 u16val &= (uint16_t)(~value);
3423 pci_write_config_word(pdev, where,
3424 u16val);
3425 }
3426 }
3427 }
3428 if (count == sizeof(uint32_t)) {
3429 if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t))
3430 goto error_out;
3431 if (where % sizeof(uint32_t))
3432 goto error_out;
3433 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
3434 pci_write_config_dword(pdev, where, value);
3435 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
3436 rc = pci_read_config_dword(pdev, where,
3437 &u32val);
3438 if (!rc) {
3439 u32val |= value;
3440 pci_write_config_dword(pdev, where,
3441 u32val);
3442 }
3443 }
3444 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
3445 rc = pci_read_config_dword(pdev, where,
3446 &u32val);
3447 if (!rc) {
3448 u32val &= ~value;
3449 pci_write_config_dword(pdev, where,
3450 u32val);
3451 }
3452 }
3453 }
3454 } else
3455 /* All other opecodes are illegal for now */
3456 goto error_out;
3457
3458 return nbytes;
3459error_out:
3460 memset(&idiag, 0, sizeof(idiag));
3461 return -EINVAL;
3462}
3463
3464/**
James Smartb76f2dc2011-07-22 18:37:42 -04003465 * lpfc_idiag_baracc_read - idiag debugfs pci bar access read
3466 * @file: The file pointer to read from.
3467 * @buf: The buffer to copy the data to.
3468 * @nbytes: The number of bytes to read.
3469 * @ppos: The position in the file to start reading from.
3470 *
3471 * Description:
3472 * This routine reads data from the @phba pci bar memory mapped space
3473 * according to the idiag command, and copies to user @buf.
3474 *
3475 * Returns:
3476 * This function returns the amount of data that was read (this could be less
3477 * than @nbytes if the end of the file was reached) or a negative error value.
3478 **/
3479static ssize_t
3480lpfc_idiag_baracc_read(struct file *file, char __user *buf, size_t nbytes,
3481 loff_t *ppos)
3482{
3483 struct lpfc_debug *debug = file->private_data;
3484 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
3485 int offset_label, offset, offset_run, len = 0, index;
3486 int bar_num, acc_range, bar_size;
3487 char *pbuffer;
3488 void __iomem *mem_mapped_bar;
3489 uint32_t if_type;
3490 struct pci_dev *pdev;
3491 uint32_t u32val;
3492
3493 pdev = phba->pcidev;
3494 if (!pdev)
3495 return 0;
3496
3497 /* This is a user read operation */
3498 debug->op = LPFC_IDIAG_OP_RD;
3499
3500 if (!debug->buffer)
3501 debug->buffer = kmalloc(LPFC_PCI_BAR_RD_BUF_SIZE, GFP_KERNEL);
3502 if (!debug->buffer)
3503 return 0;
3504 pbuffer = debug->buffer;
3505
3506 if (*ppos)
3507 return 0;
3508
3509 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) {
3510 bar_num = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX];
3511 offset = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX];
3512 acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX];
3513 bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX];
3514 } else
3515 return 0;
3516
3517 if (acc_range == 0)
3518 return 0;
3519
3520 if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
3521 if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
3522 if (bar_num == IDIAG_BARACC_BAR_0)
3523 mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
3524 else if (bar_num == IDIAG_BARACC_BAR_1)
3525 mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p;
3526 else if (bar_num == IDIAG_BARACC_BAR_2)
3527 mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p;
3528 else
3529 return 0;
3530 } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
3531 if (bar_num == IDIAG_BARACC_BAR_0)
3532 mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
3533 else
3534 return 0;
3535 } else
3536 return 0;
3537
3538 /* Read single PCI bar space register */
3539 if (acc_range == SINGLE_WORD) {
3540 offset_run = offset;
3541 u32val = readl(mem_mapped_bar + offset_run);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003542 len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04003543 "%05x: %08x\n", offset_run, u32val);
3544 } else
3545 goto baracc_browse;
3546
3547 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
3548
3549baracc_browse:
3550
3551 /* Browse all PCI bar space registers */
3552 offset_label = idiag.offset.last_rd;
3553 offset_run = offset_label;
3554
3555 /* Read PCI bar memory mapped space */
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003556 len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04003557 "%05x: ", offset_label);
3558 index = LPFC_PCI_BAR_RD_SIZE;
3559 while (index > 0) {
3560 u32val = readl(mem_mapped_bar + offset_run);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003561 len += scnprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04003562 "%08x ", u32val);
3563 offset_run += sizeof(uint32_t);
3564 if (acc_range == LPFC_PCI_BAR_BROWSE) {
3565 if (offset_run >= bar_size) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003566 len += scnprintf(pbuffer+len,
James Smartb76f2dc2011-07-22 18:37:42 -04003567 LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
3568 break;
3569 }
3570 } else {
3571 if (offset_run >= offset +
3572 (acc_range * sizeof(uint32_t))) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003573 len += scnprintf(pbuffer+len,
James Smartb76f2dc2011-07-22 18:37:42 -04003574 LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
3575 break;
3576 }
3577 }
3578 index -= sizeof(uint32_t);
3579 if (!index)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003580 len += scnprintf(pbuffer+len,
James Smartb76f2dc2011-07-22 18:37:42 -04003581 LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
3582 else if (!(index % (8 * sizeof(uint32_t)))) {
3583 offset_label += (8 * sizeof(uint32_t));
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003584 len += scnprintf(pbuffer+len,
James Smartb76f2dc2011-07-22 18:37:42 -04003585 LPFC_PCI_BAR_RD_BUF_SIZE-len,
3586 "\n%05x: ", offset_label);
3587 }
3588 }
3589
3590 /* Set up the offset for next portion of pci bar read */
3591 if (index == 0) {
3592 idiag.offset.last_rd += LPFC_PCI_BAR_RD_SIZE;
3593 if (acc_range == LPFC_PCI_BAR_BROWSE) {
3594 if (idiag.offset.last_rd >= bar_size)
3595 idiag.offset.last_rd = 0;
3596 } else {
3597 if (offset_run >= offset +
3598 (acc_range * sizeof(uint32_t)))
3599 idiag.offset.last_rd = offset;
3600 }
3601 } else {
3602 if (acc_range == LPFC_PCI_BAR_BROWSE)
3603 idiag.offset.last_rd = 0;
3604 else
3605 idiag.offset.last_rd = offset;
3606 }
3607
3608 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
3609}
3610
3611/**
3612 * lpfc_idiag_baracc_write - Syntax check and set up idiag bar access commands
3613 * @file: The file pointer to read from.
3614 * @buf: The buffer to copy the user data from.
3615 * @nbytes: The number of bytes to get.
3616 * @ppos: The position in the file to start reading from.
3617 *
3618 * This routine get the debugfs idiag command struct from user space and
3619 * then perform the syntax check for PCI bar memory mapped space read or
3620 * write command accordingly. In the case of PCI bar memory mapped space
3621 * read command, it sets up the command in the idiag command struct for
3622 * the debugfs read operation. In the case of PCI bar memorpy mapped space
3623 * write operation, it executes the write operation into the PCI bar memory
3624 * mapped space accordingly.
3625 *
3626 * It returns the @nbytges passing in from debugfs user space when successful.
3627 * In case of error conditions, it returns proper error code back to the user
3628 * space.
3629 */
3630static ssize_t
3631lpfc_idiag_baracc_write(struct file *file, const char __user *buf,
3632 size_t nbytes, loff_t *ppos)
3633{
3634 struct lpfc_debug *debug = file->private_data;
3635 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
3636 uint32_t bar_num, bar_size, offset, value, acc_range;
3637 struct pci_dev *pdev;
3638 void __iomem *mem_mapped_bar;
3639 uint32_t if_type;
3640 uint32_t u32val;
3641 int rc;
3642
3643 pdev = phba->pcidev;
3644 if (!pdev)
3645 return -EFAULT;
3646
3647 /* This is a user write operation */
3648 debug->op = LPFC_IDIAG_OP_WR;
3649
3650 rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
3651 if (rc < 0)
3652 return rc;
3653
3654 if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
3655 bar_num = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX];
3656
3657 if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
3658 if ((bar_num != IDIAG_BARACC_BAR_0) &&
3659 (bar_num != IDIAG_BARACC_BAR_1) &&
3660 (bar_num != IDIAG_BARACC_BAR_2))
3661 goto error_out;
3662 } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
3663 if (bar_num != IDIAG_BARACC_BAR_0)
3664 goto error_out;
3665 } else
3666 goto error_out;
3667
3668 if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
3669 if (bar_num == IDIAG_BARACC_BAR_0) {
3670 idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
3671 LPFC_PCI_IF0_BAR0_SIZE;
3672 mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
3673 } else if (bar_num == IDIAG_BARACC_BAR_1) {
3674 idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
3675 LPFC_PCI_IF0_BAR1_SIZE;
3676 mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p;
3677 } else if (bar_num == IDIAG_BARACC_BAR_2) {
3678 idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
3679 LPFC_PCI_IF0_BAR2_SIZE;
3680 mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p;
3681 } else
3682 goto error_out;
3683 } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
3684 if (bar_num == IDIAG_BARACC_BAR_0) {
3685 idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
3686 LPFC_PCI_IF2_BAR0_SIZE;
3687 mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
3688 } else
3689 goto error_out;
3690 } else
3691 goto error_out;
3692
3693 offset = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX];
3694 if (offset % sizeof(uint32_t))
3695 goto error_out;
3696
3697 bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX];
3698 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) {
3699 /* Sanity check on PCI config read command line arguments */
3700 if (rc != LPFC_PCI_BAR_RD_CMD_ARG)
3701 goto error_out;
3702 acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX];
3703 if (acc_range == LPFC_PCI_BAR_BROWSE) {
3704 if (offset > bar_size - sizeof(uint32_t))
3705 goto error_out;
3706 /* Starting offset to browse */
3707 idiag.offset.last_rd = offset;
3708 } else if (acc_range > SINGLE_WORD) {
3709 if (offset + acc_range * sizeof(uint32_t) > bar_size)
3710 goto error_out;
3711 /* Starting offset to browse */
3712 idiag.offset.last_rd = offset;
3713 } else if (acc_range != SINGLE_WORD)
3714 goto error_out;
3715 } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR ||
3716 idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST ||
3717 idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) {
3718 /* Sanity check on PCI bar write command line arguments */
3719 if (rc != LPFC_PCI_BAR_WR_CMD_ARG)
3720 goto error_out;
3721 /* Write command to PCI bar space, read-modify-write */
3722 acc_range = SINGLE_WORD;
3723 value = idiag.cmd.data[IDIAG_BARACC_REG_VAL_INDX];
3724 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR) {
3725 writel(value, mem_mapped_bar + offset);
3726 readl(mem_mapped_bar + offset);
3727 }
3728 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST) {
3729 u32val = readl(mem_mapped_bar + offset);
3730 u32val |= value;
3731 writel(u32val, mem_mapped_bar + offset);
3732 readl(mem_mapped_bar + offset);
3733 }
3734 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) {
3735 u32val = readl(mem_mapped_bar + offset);
3736 u32val &= ~value;
3737 writel(u32val, mem_mapped_bar + offset);
3738 readl(mem_mapped_bar + offset);
3739 }
3740 } else
3741 /* All other opecodes are illegal for now */
3742 goto error_out;
3743
3744 return nbytes;
3745error_out:
3746 memset(&idiag, 0, sizeof(idiag));
3747 return -EINVAL;
3748}
3749
James Smart07bcd982017-02-12 13:52:28 -08003750static int
3751__lpfc_idiag_print_wq(struct lpfc_queue *qp, char *wqtype,
3752 char *pbuffer, int len)
3753{
3754 if (!qp)
3755 return len;
3756
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003757 len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
James Smart07bcd982017-02-12 13:52:28 -08003758 "\t\t%s WQ info: ", wqtype);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003759 len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
James Smart07bcd982017-02-12 13:52:28 -08003760 "AssocCQID[%04d]: WQ-STAT[oflow:x%x posted:x%llx]\n",
3761 qp->assoc_qid, qp->q_cnt_1,
3762 (unsigned long long)qp->q_cnt_4);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003763 len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
James Smart7869da12017-05-15 15:20:43 -07003764 "\t\tWQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
James Smart32517fc2019-01-28 11:14:33 -08003765 "HST-IDX[%04d], PRT-IDX[%04d], NTFI[%03d]",
James Smart07bcd982017-02-12 13:52:28 -08003766 qp->queue_id, qp->entry_count,
3767 qp->entry_size, qp->host_index,
James Smart32517fc2019-01-28 11:14:33 -08003768 qp->hba_index, qp->notify_interval);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003769 len += scnprintf(pbuffer + len,
James Smart07bcd982017-02-12 13:52:28 -08003770 LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n");
3771 return len;
3772}
3773
3774static int
3775lpfc_idiag_wqs_for_cq(struct lpfc_hba *phba, char *wqtype, char *pbuffer,
3776 int *len, int max_cnt, int cq_id)
3777{
3778 struct lpfc_queue *qp;
3779 int qidx;
3780
James Smartcdb42be2019-01-28 11:14:21 -08003781 for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) {
James Smartc00f62e2019-08-14 16:57:11 -07003782 qp = phba->sli4_hba.hdwq[qidx].io_wq;
James Smart07bcd982017-02-12 13:52:28 -08003783 if (qp->assoc_qid != cq_id)
3784 continue;
3785 *len = __lpfc_idiag_print_wq(qp, wqtype, pbuffer, *len);
3786 if (*len >= max_cnt)
3787 return 1;
3788 }
3789 return 0;
3790}
3791
3792static int
3793__lpfc_idiag_print_cq(struct lpfc_queue *qp, char *cqtype,
3794 char *pbuffer, int len)
3795{
3796 if (!qp)
3797 return len;
3798
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003799 len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
James Smart07bcd982017-02-12 13:52:28 -08003800 "\t%s CQ info: ", cqtype);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003801 len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
James Smart07bcd982017-02-12 13:52:28 -08003802 "AssocEQID[%02d]: CQ STAT[max:x%x relw:x%x "
3803 "xabt:x%x wq:x%llx]\n",
3804 qp->assoc_qid, qp->q_cnt_1, qp->q_cnt_2,
3805 qp->q_cnt_3, (unsigned long long)qp->q_cnt_4);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003806 len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
James Smart7869da12017-05-15 15:20:43 -07003807 "\tCQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
James Smart32517fc2019-01-28 11:14:33 -08003808 "HST-IDX[%04d], NTFI[%03d], PLMT[%03d]",
James Smart07bcd982017-02-12 13:52:28 -08003809 qp->queue_id, qp->entry_count,
3810 qp->entry_size, qp->host_index,
James Smart32517fc2019-01-28 11:14:33 -08003811 qp->notify_interval, qp->max_proc_limit);
James Smart07bcd982017-02-12 13:52:28 -08003812
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003813 len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3814 "\n");
James Smart07bcd982017-02-12 13:52:28 -08003815
3816 return len;
3817}
3818
3819static int
3820__lpfc_idiag_print_rqpair(struct lpfc_queue *qp, struct lpfc_queue *datqp,
3821 char *rqtype, char *pbuffer, int len)
3822{
3823 if (!qp || !datqp)
3824 return len;
3825
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003826 len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
James Smart07bcd982017-02-12 13:52:28 -08003827 "\t\t%s RQ info: ", rqtype);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003828 len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
James Smart07bcd982017-02-12 13:52:28 -08003829 "AssocCQID[%02d]: RQ-STAT[nopost:x%x nobuf:x%x "
James Smart547077a2017-05-15 15:20:40 -07003830 "posted:x%x rcv:x%llx]\n",
James Smart07bcd982017-02-12 13:52:28 -08003831 qp->assoc_qid, qp->q_cnt_1, qp->q_cnt_2,
3832 qp->q_cnt_3, (unsigned long long)qp->q_cnt_4);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003833 len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
James Smart7869da12017-05-15 15:20:43 -07003834 "\t\tHQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
James Smart32517fc2019-01-28 11:14:33 -08003835 "HST-IDX[%04d], PRT-IDX[%04d], NTFI[%03d]\n",
James Smart07bcd982017-02-12 13:52:28 -08003836 qp->queue_id, qp->entry_count, qp->entry_size,
James Smart32517fc2019-01-28 11:14:33 -08003837 qp->host_index, qp->hba_index, qp->notify_interval);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003838 len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
James Smart7869da12017-05-15 15:20:43 -07003839 "\t\tDQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
James Smart32517fc2019-01-28 11:14:33 -08003840 "HST-IDX[%04d], PRT-IDX[%04d], NTFI[%03d]\n",
James Smart07bcd982017-02-12 13:52:28 -08003841 datqp->queue_id, datqp->entry_count,
3842 datqp->entry_size, datqp->host_index,
James Smart32517fc2019-01-28 11:14:33 -08003843 datqp->hba_index, datqp->notify_interval);
James Smart07bcd982017-02-12 13:52:28 -08003844 return len;
3845}
3846
3847static int
3848lpfc_idiag_cqs_for_eq(struct lpfc_hba *phba, char *pbuffer,
James Smart2d7dbc42017-02-12 13:52:35 -08003849 int *len, int max_cnt, int eqidx, int eq_id)
James Smart07bcd982017-02-12 13:52:28 -08003850{
3851 struct lpfc_queue *qp;
James Smart6a828b02019-01-28 11:14:31 -08003852 int rc;
James Smart07bcd982017-02-12 13:52:28 -08003853
James Smartc00f62e2019-08-14 16:57:11 -07003854 qp = phba->sli4_hba.hdwq[eqidx].io_cq;
James Smart07bcd982017-02-12 13:52:28 -08003855
James Smartc00f62e2019-08-14 16:57:11 -07003856 *len = __lpfc_idiag_print_cq(qp, "IO", pbuffer, *len);
James Smart6a828b02019-01-28 11:14:31 -08003857
3858 /* Reset max counter */
3859 qp->CQ_max_cqe = 0;
3860
3861 if (*len >= max_cnt)
3862 return 1;
3863
James Smartc00f62e2019-08-14 16:57:11 -07003864 rc = lpfc_idiag_wqs_for_cq(phba, "IO", pbuffer, len,
James Smart6a828b02019-01-28 11:14:31 -08003865 max_cnt, qp->queue_id);
3866 if (rc)
3867 return 1;
3868
James Smartbcb24f62017-11-20 16:00:36 -08003869 if ((eqidx < phba->cfg_nvmet_mrq) && phba->nvmet_support) {
James Smart2d7dbc42017-02-12 13:52:35 -08003870 /* NVMET CQset */
3871 qp = phba->sli4_hba.nvmet_cqset[eqidx];
3872 *len = __lpfc_idiag_print_cq(qp, "NVMET CQset", pbuffer, *len);
3873
3874 /* Reset max counter */
3875 qp->CQ_max_cqe = 0;
3876
3877 if (*len >= max_cnt)
3878 return 1;
3879
3880 /* RQ header */
3881 qp = phba->sli4_hba.nvmet_mrq_hdr[eqidx];
3882 *len = __lpfc_idiag_print_rqpair(qp,
3883 phba->sli4_hba.nvmet_mrq_data[eqidx],
3884 "NVMET MRQ", pbuffer, *len);
3885
3886 if (*len >= max_cnt)
3887 return 1;
3888 }
3889
James Smart07bcd982017-02-12 13:52:28 -08003890 return 0;
3891}
3892
3893static int
3894__lpfc_idiag_print_eq(struct lpfc_queue *qp, char *eqtype,
3895 char *pbuffer, int len)
3896{
3897 if (!qp)
3898 return len;
3899
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003900 len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
James Smart07bcd982017-02-12 13:52:28 -08003901 "\n%s EQ info: EQ-STAT[max:x%x noE:x%x "
James Smart07d494f2017-11-20 16:00:35 -08003902 "cqe_proc:x%x eqe_proc:x%llx eqd %d]\n",
James Smart07bcd982017-02-12 13:52:28 -08003903 eqtype, qp->q_cnt_1, qp->q_cnt_2, qp->q_cnt_3,
James Smart0cf07f842017-06-01 21:07:10 -07003904 (unsigned long long)qp->q_cnt_4, qp->q_mode);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003905 len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
James Smart7869da12017-05-15 15:20:43 -07003906 "EQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
James Smart32517fc2019-01-28 11:14:33 -08003907 "HST-IDX[%04d], NTFI[%03d], PLMT[%03d], AFFIN[%03d]",
James Smart07bcd982017-02-12 13:52:28 -08003908 qp->queue_id, qp->entry_count, qp->entry_size,
James Smart32517fc2019-01-28 11:14:33 -08003909 qp->host_index, qp->notify_interval,
3910 qp->max_proc_limit, qp->chann);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003911 len += scnprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
3912 "\n");
James Smart07bcd982017-02-12 13:52:28 -08003913
3914 return len;
3915}
3916
James Smartb76f2dc2011-07-22 18:37:42 -04003917/**
James Smart2a622bf2011-02-16 12:40:06 -05003918 * lpfc_idiag_queinfo_read - idiag debugfs read queue information
3919 * @file: The file pointer to read from.
3920 * @buf: The buffer to copy the data to.
3921 * @nbytes: The number of bytes to read.
3922 * @ppos: The position in the file to start reading from.
3923 *
3924 * Description:
3925 * This routine reads data from the @phba SLI4 PCI function queue information,
3926 * and copies to user @buf.
James Smart07bcd982017-02-12 13:52:28 -08003927 * This routine only returns 1 EQs worth of information. It remembers the last
3928 * EQ read and jumps to the next EQ. Thus subsequent calls to queInfo will
3929 * retrieve all EQs allocated for the phba.
James Smart2a622bf2011-02-16 12:40:06 -05003930 *
3931 * Returns:
3932 * This function returns the amount of data that was read (this could be less
3933 * than @nbytes if the end of the file was reached) or a negative error value.
3934 **/
3935static ssize_t
3936lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
3937 loff_t *ppos)
3938{
3939 struct lpfc_debug *debug = file->private_data;
3940 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
James Smart2a622bf2011-02-16 12:40:06 -05003941 char *pbuffer;
James Smart07bcd982017-02-12 13:52:28 -08003942 int max_cnt, rc, x, len = 0;
James Smartc85a65a2012-08-03 12:37:00 -04003943 struct lpfc_queue *qp = NULL;
3944
James Smart2a622bf2011-02-16 12:40:06 -05003945 if (!debug->buffer)
3946 debug->buffer = kmalloc(LPFC_QUE_INFO_GET_BUF_SIZE, GFP_KERNEL);
3947 if (!debug->buffer)
3948 return 0;
3949 pbuffer = debug->buffer;
James Smart07bcd982017-02-12 13:52:28 -08003950 max_cnt = LPFC_QUE_INFO_GET_BUF_SIZE - 256;
James Smart2a622bf2011-02-16 12:40:06 -05003951
3952 if (*ppos)
3953 return 0;
3954
James Smartc85a65a2012-08-03 12:37:00 -04003955 spin_lock_irq(&phba->hbalock);
James Smart2a622bf2011-02-16 12:40:06 -05003956
James Smartc85a65a2012-08-03 12:37:00 -04003957 /* Fast-path event queue */
James Smartcdb42be2019-01-28 11:14:21 -08003958 if (phba->sli4_hba.hdwq && phba->cfg_hdw_queue) {
James Smart2a622bf2011-02-16 12:40:06 -05003959
James Smart07bcd982017-02-12 13:52:28 -08003960 x = phba->lpfc_idiag_last_eq;
James Smart07bcd982017-02-12 13:52:28 -08003961 phba->lpfc_idiag_last_eq++;
James Smartcdb42be2019-01-28 11:14:21 -08003962 if (phba->lpfc_idiag_last_eq >= phba->cfg_hdw_queue)
James Smart7370d102019-01-28 11:14:20 -08003963 phba->lpfc_idiag_last_eq = 0;
James Smart2a622bf2011-02-16 12:40:06 -05003964
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07003965 len += scnprintf(pbuffer + len,
3966 LPFC_QUE_INFO_GET_BUF_SIZE - len,
3967 "HDWQ %d out of %d HBA HDWQs\n",
3968 x, phba->cfg_hdw_queue);
James Smart07bcd982017-02-12 13:52:28 -08003969
3970 /* Fast-path EQ */
James Smartcdb42be2019-01-28 11:14:21 -08003971 qp = phba->sli4_hba.hdwq[x].hba_eq;
James Smart1ba981f2014-02-20 09:56:45 -05003972 if (!qp)
3973 goto out;
3974
James Smart07bcd982017-02-12 13:52:28 -08003975 len = __lpfc_idiag_print_eq(qp, "HBA", pbuffer, len);
James Smart1ba981f2014-02-20 09:56:45 -05003976
3977 /* Reset max counter */
3978 qp->EQ_max_eqe = 0;
3979
James Smart07bcd982017-02-12 13:52:28 -08003980 if (len >= max_cnt)
3981 goto too_big;
3982
James Smart895427b2017-02-12 13:52:30 -08003983 /* will dump both fcp and nvme cqs/wqs for the eq */
James Smart07bcd982017-02-12 13:52:28 -08003984 rc = lpfc_idiag_cqs_for_eq(phba, pbuffer, &len,
James Smart2d7dbc42017-02-12 13:52:35 -08003985 max_cnt, x, qp->queue_id);
James Smart07bcd982017-02-12 13:52:28 -08003986 if (rc)
3987 goto too_big;
3988
3989 /* Only EQ 0 has slow path CQs configured */
3990 if (x)
3991 goto out;
3992
3993 /* Slow-path mailbox CQ */
3994 qp = phba->sli4_hba.mbx_cq;
3995 len = __lpfc_idiag_print_cq(qp, "MBX", pbuffer, len);
3996 if (len >= max_cnt)
3997 goto too_big;
3998
3999 /* Slow-path MBOX MQ */
4000 qp = phba->sli4_hba.mbx_wq;
4001 len = __lpfc_idiag_print_wq(qp, "MBX", pbuffer, len);
4002 if (len >= max_cnt)
4003 goto too_big;
4004
4005 /* Slow-path ELS response CQ */
4006 qp = phba->sli4_hba.els_cq;
4007 len = __lpfc_idiag_print_cq(qp, "ELS", pbuffer, len);
4008 /* Reset max counter */
4009 if (qp)
4010 qp->CQ_max_cqe = 0;
4011 if (len >= max_cnt)
4012 goto too_big;
4013
4014 /* Slow-path ELS WQ */
4015 qp = phba->sli4_hba.els_wq;
4016 len = __lpfc_idiag_print_wq(qp, "ELS", pbuffer, len);
4017 if (len >= max_cnt)
4018 goto too_big;
4019
James Smart07d494f2017-11-20 16:00:35 -08004020 qp = phba->sli4_hba.hdr_rq;
4021 len = __lpfc_idiag_print_rqpair(qp, phba->sli4_hba.dat_rq,
4022 "ELS RQpair", pbuffer, len);
4023 if (len >= max_cnt)
4024 goto too_big;
4025
James Smart895427b2017-02-12 13:52:30 -08004026 /* Slow-path NVME LS response CQ */
4027 qp = phba->sli4_hba.nvmels_cq;
4028 len = __lpfc_idiag_print_cq(qp, "NVME LS",
4029 pbuffer, len);
4030 /* Reset max counter */
4031 if (qp)
4032 qp->CQ_max_cqe = 0;
4033 if (len >= max_cnt)
4034 goto too_big;
4035
4036 /* Slow-path NVME LS WQ */
4037 qp = phba->sli4_hba.nvmels_wq;
4038 len = __lpfc_idiag_print_wq(qp, "NVME LS",
4039 pbuffer, len);
4040 if (len >= max_cnt)
4041 goto too_big;
4042
James Smart07bcd982017-02-12 13:52:28 -08004043 goto out;
4044 }
4045
James Smartc85a65a2012-08-03 12:37:00 -04004046 spin_unlock_irq(&phba->hbalock);
4047 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
4048
4049too_big:
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004050 len += scnprintf(pbuffer + len,
James Smart07bcd982017-02-12 13:52:28 -08004051 LPFC_QUE_INFO_GET_BUF_SIZE - len, "Truncated ...\n");
4052out:
James Smartc85a65a2012-08-03 12:37:00 -04004053 spin_unlock_irq(&phba->hbalock);
James Smart2a622bf2011-02-16 12:40:06 -05004054 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
4055}
4056
James Smart86a80842011-04-16 11:03:04 -04004057/**
4058 * lpfc_idiag_que_param_check - queue access command parameter sanity check
4059 * @q: The pointer to queue structure.
4060 * @index: The index into a queue entry.
4061 * @count: The number of queue entries to access.
4062 *
4063 * Description:
4064 * The routine performs sanity check on device queue access method commands.
4065 *
4066 * Returns:
4067 * This function returns -EINVAL when fails the sanity check, otherwise, it
4068 * returns 0.
4069 **/
4070static int
4071lpfc_idiag_que_param_check(struct lpfc_queue *q, int index, int count)
4072{
4073 /* Only support single entry read or browsing */
4074 if ((count != 1) && (count != LPFC_QUE_ACC_BROWSE))
4075 return -EINVAL;
4076 if (index > q->entry_count - 1)
4077 return -EINVAL;
4078 return 0;
4079}
4080
4081/**
4082 * lpfc_idiag_queacc_read_qe - read a single entry from the given queue index
4083 * @pbuffer: The pointer to buffer to copy the read data into.
4084 * @pque: The pointer to the queue to be read.
4085 * @index: The index into the queue entry.
4086 *
4087 * Description:
4088 * This routine reads out a single entry from the given queue's index location
4089 * and copies it into the buffer provided.
4090 *
4091 * Returns:
4092 * This function returns 0 when it fails, otherwise, it returns the length of
4093 * the data read into the buffer provided.
4094 **/
4095static int
4096lpfc_idiag_queacc_read_qe(char *pbuffer, int len, struct lpfc_queue *pque,
4097 uint32_t index)
4098{
4099 int offset, esize;
4100 uint32_t *pentry;
4101
4102 if (!pbuffer || !pque)
4103 return 0;
4104
4105 esize = pque->entry_size;
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004106 len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len,
James Smart86a80842011-04-16 11:03:04 -04004107 "QE-INDEX[%04d]:\n", index);
4108
4109 offset = 0;
James Smart9afbee32019-03-12 16:30:28 -07004110 pentry = lpfc_sli4_qe(pque, index);
James Smart86a80842011-04-16 11:03:04 -04004111 while (esize > 0) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004112 len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len,
James Smart86a80842011-04-16 11:03:04 -04004113 "%08x ", *pentry);
4114 pentry++;
4115 offset += sizeof(uint32_t);
4116 esize -= sizeof(uint32_t);
4117 if (esize > 0 && !(offset % (4 * sizeof(uint32_t))))
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004118 len += scnprintf(pbuffer+len,
James Smart86a80842011-04-16 11:03:04 -04004119 LPFC_QUE_ACC_BUF_SIZE-len, "\n");
4120 }
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004121 len += scnprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, "\n");
James Smart86a80842011-04-16 11:03:04 -04004122
4123 return len;
4124}
4125
4126/**
4127 * lpfc_idiag_queacc_read - idiag debugfs read port queue
4128 * @file: The file pointer to read from.
4129 * @buf: The buffer to copy the data to.
4130 * @nbytes: The number of bytes to read.
4131 * @ppos: The position in the file to start reading from.
4132 *
4133 * Description:
4134 * This routine reads data from the @phba device queue memory according to the
4135 * idiag command, and copies to user @buf. Depending on the queue dump read
4136 * command setup, it does either a single queue entry read or browing through
4137 * all entries of the queue.
4138 *
4139 * Returns:
4140 * This function returns the amount of data that was read (this could be less
4141 * than @nbytes if the end of the file was reached) or a negative error value.
4142 **/
4143static ssize_t
4144lpfc_idiag_queacc_read(struct file *file, char __user *buf, size_t nbytes,
4145 loff_t *ppos)
4146{
4147 struct lpfc_debug *debug = file->private_data;
4148 uint32_t last_index, index, count;
4149 struct lpfc_queue *pque = NULL;
4150 char *pbuffer;
4151 int len = 0;
4152
4153 /* This is a user read operation */
4154 debug->op = LPFC_IDIAG_OP_RD;
4155
4156 if (!debug->buffer)
4157 debug->buffer = kmalloc(LPFC_QUE_ACC_BUF_SIZE, GFP_KERNEL);
4158 if (!debug->buffer)
4159 return 0;
4160 pbuffer = debug->buffer;
4161
4162 if (*ppos)
4163 return 0;
4164
4165 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
James Smartb76f2dc2011-07-22 18:37:42 -04004166 index = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX];
4167 count = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX];
James Smart86a80842011-04-16 11:03:04 -04004168 pque = (struct lpfc_queue *)idiag.ptr_private;
4169 } else
4170 return 0;
4171
4172 /* Browse the queue starting from index */
4173 if (count == LPFC_QUE_ACC_BROWSE)
4174 goto que_browse;
4175
4176 /* Read a single entry from the queue */
4177 len = lpfc_idiag_queacc_read_qe(pbuffer, len, pque, index);
4178
4179 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
4180
4181que_browse:
4182
4183 /* Browse all entries from the queue */
4184 last_index = idiag.offset.last_rd;
4185 index = last_index;
4186
4187 while (len < LPFC_QUE_ACC_SIZE - pque->entry_size) {
4188 len = lpfc_idiag_queacc_read_qe(pbuffer, len, pque, index);
4189 index++;
4190 if (index > pque->entry_count - 1)
4191 break;
4192 }
4193
4194 /* Set up the offset for next portion of pci cfg read */
4195 if (index > pque->entry_count - 1)
4196 index = 0;
4197 idiag.offset.last_rd = index;
4198
4199 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
4200}
4201
4202/**
4203 * lpfc_idiag_queacc_write - Syntax check and set up idiag queacc commands
4204 * @file: The file pointer to read from.
4205 * @buf: The buffer to copy the user data from.
4206 * @nbytes: The number of bytes to get.
4207 * @ppos: The position in the file to start reading from.
4208 *
4209 * This routine get the debugfs idiag command struct from user space and then
4210 * perform the syntax check for port queue read (dump) or write (set) command
4211 * accordingly. In the case of port queue read command, it sets up the command
4212 * in the idiag command struct for the following debugfs read operation. In
4213 * the case of port queue write operation, it executes the write operation
4214 * into the port queue entry accordingly.
4215 *
4216 * It returns the @nbytges passing in from debugfs user space when successful.
4217 * In case of error conditions, it returns proper error code back to the user
4218 * space.
4219 **/
4220static ssize_t
4221lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
4222 size_t nbytes, loff_t *ppos)
4223{
4224 struct lpfc_debug *debug = file->private_data;
4225 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
4226 uint32_t qidx, quetp, queid, index, count, offset, value;
4227 uint32_t *pentry;
James Smart895427b2017-02-12 13:52:30 -08004228 struct lpfc_queue *pque, *qp;
James Smart86a80842011-04-16 11:03:04 -04004229 int rc;
4230
4231 /* This is a user write operation */
4232 debug->op = LPFC_IDIAG_OP_WR;
4233
4234 rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
4235 if (rc < 0)
4236 return rc;
4237
4238 /* Get and sanity check on command feilds */
James Smartb76f2dc2011-07-22 18:37:42 -04004239 quetp = idiag.cmd.data[IDIAG_QUEACC_QUETP_INDX];
4240 queid = idiag.cmd.data[IDIAG_QUEACC_QUEID_INDX];
4241 index = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX];
4242 count = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX];
4243 offset = idiag.cmd.data[IDIAG_QUEACC_OFFST_INDX];
4244 value = idiag.cmd.data[IDIAG_QUEACC_VALUE_INDX];
James Smart86a80842011-04-16 11:03:04 -04004245
4246 /* Sanity check on command line arguments */
4247 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR ||
4248 idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST ||
4249 idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL) {
4250 if (rc != LPFC_QUE_ACC_WR_CMD_ARG)
4251 goto error_out;
4252 if (count != 1)
4253 goto error_out;
4254 } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
4255 if (rc != LPFC_QUE_ACC_RD_CMD_ARG)
4256 goto error_out;
4257 } else
4258 goto error_out;
4259
4260 switch (quetp) {
4261 case LPFC_IDIAG_EQ:
James Smart67d12732012-08-03 12:36:13 -04004262 /* HBA event queue */
James Smartcdb42be2019-01-28 11:14:21 -08004263 if (phba->sli4_hba.hdwq) {
4264 for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) {
4265 qp = phba->sli4_hba.hdwq[qidx].hba_eq;
James Smart895427b2017-02-12 13:52:30 -08004266 if (qp && qp->queue_id == queid) {
James Smart2e90f4b2011-12-13 13:22:37 -05004267 /* Sanity check */
James Smart895427b2017-02-12 13:52:30 -08004268 rc = lpfc_idiag_que_param_check(qp,
James Smart86a80842011-04-16 11:03:04 -04004269 index, count);
James Smart2e90f4b2011-12-13 13:22:37 -05004270 if (rc)
4271 goto error_out;
James Smart895427b2017-02-12 13:52:30 -08004272 idiag.ptr_private = qp;
James Smart2e90f4b2011-12-13 13:22:37 -05004273 goto pass_check;
4274 }
James Smart86a80842011-04-16 11:03:04 -04004275 }
4276 }
4277 goto error_out;
4278 break;
4279 case LPFC_IDIAG_CQ:
4280 /* MBX complete queue */
James Smart2e90f4b2011-12-13 13:22:37 -05004281 if (phba->sli4_hba.mbx_cq &&
4282 phba->sli4_hba.mbx_cq->queue_id == queid) {
James Smart86a80842011-04-16 11:03:04 -04004283 /* Sanity check */
4284 rc = lpfc_idiag_que_param_check(
4285 phba->sli4_hba.mbx_cq, index, count);
4286 if (rc)
4287 goto error_out;
4288 idiag.ptr_private = phba->sli4_hba.mbx_cq;
4289 goto pass_check;
4290 }
4291 /* ELS complete queue */
James Smart2e90f4b2011-12-13 13:22:37 -05004292 if (phba->sli4_hba.els_cq &&
4293 phba->sli4_hba.els_cq->queue_id == queid) {
James Smart86a80842011-04-16 11:03:04 -04004294 /* Sanity check */
4295 rc = lpfc_idiag_que_param_check(
4296 phba->sli4_hba.els_cq, index, count);
4297 if (rc)
4298 goto error_out;
4299 idiag.ptr_private = phba->sli4_hba.els_cq;
4300 goto pass_check;
4301 }
James Smart895427b2017-02-12 13:52:30 -08004302 /* NVME LS complete queue */
4303 if (phba->sli4_hba.nvmels_cq &&
4304 phba->sli4_hba.nvmels_cq->queue_id == queid) {
4305 /* Sanity check */
4306 rc = lpfc_idiag_que_param_check(
4307 phba->sli4_hba.nvmels_cq, index, count);
4308 if (rc)
4309 goto error_out;
4310 idiag.ptr_private = phba->sli4_hba.nvmels_cq;
4311 goto pass_check;
4312 }
James Smart86a80842011-04-16 11:03:04 -04004313 /* FCP complete queue */
James Smartcdb42be2019-01-28 11:14:21 -08004314 if (phba->sli4_hba.hdwq) {
4315 for (qidx = 0; qidx < phba->cfg_hdw_queue;
James Smart895427b2017-02-12 13:52:30 -08004316 qidx++) {
James Smartc00f62e2019-08-14 16:57:11 -07004317 qp = phba->sli4_hba.hdwq[qidx].io_cq;
James Smart895427b2017-02-12 13:52:30 -08004318 if (qp && qp->queue_id == queid) {
James Smart2e90f4b2011-12-13 13:22:37 -05004319 /* Sanity check */
4320 rc = lpfc_idiag_que_param_check(
James Smart895427b2017-02-12 13:52:30 -08004321 qp, index, count);
James Smart2e90f4b2011-12-13 13:22:37 -05004322 if (rc)
4323 goto error_out;
James Smart895427b2017-02-12 13:52:30 -08004324 idiag.ptr_private = qp;
James Smart2e90f4b2011-12-13 13:22:37 -05004325 goto pass_check;
4326 }
James Smart895427b2017-02-12 13:52:30 -08004327 }
James Smart2e90f4b2011-12-13 13:22:37 -05004328 }
James Smart86a80842011-04-16 11:03:04 -04004329 goto error_out;
4330 break;
4331 case LPFC_IDIAG_MQ:
4332 /* MBX work queue */
James Smart2e90f4b2011-12-13 13:22:37 -05004333 if (phba->sli4_hba.mbx_wq &&
4334 phba->sli4_hba.mbx_wq->queue_id == queid) {
James Smart86a80842011-04-16 11:03:04 -04004335 /* Sanity check */
4336 rc = lpfc_idiag_que_param_check(
4337 phba->sli4_hba.mbx_wq, index, count);
4338 if (rc)
4339 goto error_out;
4340 idiag.ptr_private = phba->sli4_hba.mbx_wq;
4341 goto pass_check;
4342 }
James Smart2e90f4b2011-12-13 13:22:37 -05004343 goto error_out;
James Smart86a80842011-04-16 11:03:04 -04004344 break;
4345 case LPFC_IDIAG_WQ:
4346 /* ELS work queue */
James Smart2e90f4b2011-12-13 13:22:37 -05004347 if (phba->sli4_hba.els_wq &&
4348 phba->sli4_hba.els_wq->queue_id == queid) {
James Smart86a80842011-04-16 11:03:04 -04004349 /* Sanity check */
4350 rc = lpfc_idiag_que_param_check(
4351 phba->sli4_hba.els_wq, index, count);
4352 if (rc)
4353 goto error_out;
4354 idiag.ptr_private = phba->sli4_hba.els_wq;
4355 goto pass_check;
4356 }
James Smart895427b2017-02-12 13:52:30 -08004357 /* NVME LS work queue */
4358 if (phba->sli4_hba.nvmels_wq &&
4359 phba->sli4_hba.nvmels_wq->queue_id == queid) {
4360 /* Sanity check */
4361 rc = lpfc_idiag_que_param_check(
4362 phba->sli4_hba.nvmels_wq, index, count);
4363 if (rc)
4364 goto error_out;
4365 idiag.ptr_private = phba->sli4_hba.nvmels_wq;
4366 goto pass_check;
4367 }
James Smartcdb42be2019-01-28 11:14:21 -08004368
4369 if (phba->sli4_hba.hdwq) {
4370 /* FCP/SCSI work queue */
4371 for (qidx = 0; qidx < phba->cfg_hdw_queue; qidx++) {
James Smartc00f62e2019-08-14 16:57:11 -07004372 qp = phba->sli4_hba.hdwq[qidx].io_wq;
James Smart895427b2017-02-12 13:52:30 -08004373 if (qp && qp->queue_id == queid) {
4374 /* Sanity check */
4375 rc = lpfc_idiag_que_param_check(
4376 qp, index, count);
4377 if (rc)
4378 goto error_out;
4379 idiag.ptr_private = qp;
James Smart2e90f4b2011-12-13 13:22:37 -05004380 goto pass_check;
4381 }
James Smart86a80842011-04-16 11:03:04 -04004382 }
4383 }
James Smartbd2cdd52017-02-12 13:52:33 -08004384
James Smart86a80842011-04-16 11:03:04 -04004385 goto error_out;
4386 break;
4387 case LPFC_IDIAG_RQ:
4388 /* HDR queue */
James Smart2e90f4b2011-12-13 13:22:37 -05004389 if (phba->sli4_hba.hdr_rq &&
4390 phba->sli4_hba.hdr_rq->queue_id == queid) {
James Smart86a80842011-04-16 11:03:04 -04004391 /* Sanity check */
4392 rc = lpfc_idiag_que_param_check(
4393 phba->sli4_hba.hdr_rq, index, count);
4394 if (rc)
4395 goto error_out;
4396 idiag.ptr_private = phba->sli4_hba.hdr_rq;
4397 goto pass_check;
4398 }
4399 /* DAT queue */
James Smart2e90f4b2011-12-13 13:22:37 -05004400 if (phba->sli4_hba.dat_rq &&
4401 phba->sli4_hba.dat_rq->queue_id == queid) {
James Smart86a80842011-04-16 11:03:04 -04004402 /* Sanity check */
4403 rc = lpfc_idiag_que_param_check(
4404 phba->sli4_hba.dat_rq, index, count);
4405 if (rc)
4406 goto error_out;
4407 idiag.ptr_private = phba->sli4_hba.dat_rq;
4408 goto pass_check;
4409 }
4410 goto error_out;
4411 break;
4412 default:
4413 goto error_out;
4414 break;
4415 }
4416
4417pass_check:
4418
4419 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
4420 if (count == LPFC_QUE_ACC_BROWSE)
4421 idiag.offset.last_rd = index;
4422 }
4423
4424 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR ||
4425 idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST ||
4426 idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL) {
4427 /* Additional sanity checks on write operation */
4428 pque = (struct lpfc_queue *)idiag.ptr_private;
4429 if (offset > pque->entry_size/sizeof(uint32_t) - 1)
4430 goto error_out;
James Smart9afbee32019-03-12 16:30:28 -07004431 pentry = lpfc_sli4_qe(pque, index);
James Smart86a80842011-04-16 11:03:04 -04004432 pentry += offset;
4433 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR)
4434 *pentry = value;
4435 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST)
4436 *pentry |= value;
4437 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL)
4438 *pentry &= ~value;
4439 }
4440 return nbytes;
4441
4442error_out:
4443 /* Clean out command structure on command error out */
4444 memset(&idiag, 0, sizeof(idiag));
4445 return -EINVAL;
4446}
4447
4448/**
4449 * lpfc_idiag_drbacc_read_reg - idiag debugfs read a doorbell register
4450 * @phba: The pointer to hba structure.
4451 * @pbuffer: The pointer to the buffer to copy the data to.
Matteo Croce92684bf2019-01-04 22:38:54 +01004452 * @len: The length of bytes to copied.
James Smart86a80842011-04-16 11:03:04 -04004453 * @drbregid: The id to doorbell registers.
4454 *
4455 * Description:
4456 * This routine reads a doorbell register and copies its content to the
4457 * user buffer pointed to by @pbuffer.
4458 *
4459 * Returns:
4460 * This function returns the amount of data that was copied into @pbuffer.
4461 **/
4462static int
4463lpfc_idiag_drbacc_read_reg(struct lpfc_hba *phba, char *pbuffer,
4464 int len, uint32_t drbregid)
4465{
4466
4467 if (!pbuffer)
4468 return 0;
4469
4470 switch (drbregid) {
James Smart9dd35422018-02-22 08:18:41 -08004471 case LPFC_DRB_EQ:
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004472 len += scnprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE-len,
James Smart9dd35422018-02-22 08:18:41 -08004473 "EQ-DRB-REG: 0x%08x\n",
4474 readl(phba->sli4_hba.EQDBregaddr));
4475 break;
4476 case LPFC_DRB_CQ:
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004477 len += scnprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE - len,
James Smart9dd35422018-02-22 08:18:41 -08004478 "CQ-DRB-REG: 0x%08x\n",
4479 readl(phba->sli4_hba.CQDBregaddr));
James Smart86a80842011-04-16 11:03:04 -04004480 break;
4481 case LPFC_DRB_MQ:
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004482 len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
James Smart86a80842011-04-16 11:03:04 -04004483 "MQ-DRB-REG: 0x%08x\n",
4484 readl(phba->sli4_hba.MQDBregaddr));
4485 break;
4486 case LPFC_DRB_WQ:
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004487 len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
James Smart86a80842011-04-16 11:03:04 -04004488 "WQ-DRB-REG: 0x%08x\n",
4489 readl(phba->sli4_hba.WQDBregaddr));
4490 break;
4491 case LPFC_DRB_RQ:
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004492 len += scnprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
James Smart86a80842011-04-16 11:03:04 -04004493 "RQ-DRB-REG: 0x%08x\n",
4494 readl(phba->sli4_hba.RQDBregaddr));
4495 break;
4496 default:
4497 break;
4498 }
4499
4500 return len;
4501}
4502
4503/**
4504 * lpfc_idiag_drbacc_read - idiag debugfs read port doorbell
4505 * @file: The file pointer to read from.
4506 * @buf: The buffer to copy the data to.
4507 * @nbytes: The number of bytes to read.
4508 * @ppos: The position in the file to start reading from.
4509 *
4510 * Description:
4511 * This routine reads data from the @phba device doorbell register according
4512 * to the idiag command, and copies to user @buf. Depending on the doorbell
4513 * register read command setup, it does either a single doorbell register
4514 * read or dump all doorbell registers.
4515 *
4516 * Returns:
4517 * This function returns the amount of data that was read (this could be less
4518 * than @nbytes if the end of the file was reached) or a negative error value.
4519 **/
4520static ssize_t
4521lpfc_idiag_drbacc_read(struct file *file, char __user *buf, size_t nbytes,
4522 loff_t *ppos)
4523{
4524 struct lpfc_debug *debug = file->private_data;
4525 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
4526 uint32_t drb_reg_id, i;
4527 char *pbuffer;
4528 int len = 0;
4529
4530 /* This is a user read operation */
4531 debug->op = LPFC_IDIAG_OP_RD;
4532
4533 if (!debug->buffer)
4534 debug->buffer = kmalloc(LPFC_DRB_ACC_BUF_SIZE, GFP_KERNEL);
4535 if (!debug->buffer)
4536 return 0;
4537 pbuffer = debug->buffer;
4538
4539 if (*ppos)
4540 return 0;
4541
4542 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD)
James Smartb76f2dc2011-07-22 18:37:42 -04004543 drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX];
James Smart86a80842011-04-16 11:03:04 -04004544 else
4545 return 0;
4546
4547 if (drb_reg_id == LPFC_DRB_ACC_ALL)
4548 for (i = 1; i <= LPFC_DRB_MAX; i++)
4549 len = lpfc_idiag_drbacc_read_reg(phba,
4550 pbuffer, len, i);
4551 else
4552 len = lpfc_idiag_drbacc_read_reg(phba,
4553 pbuffer, len, drb_reg_id);
4554
4555 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
4556}
4557
4558/**
4559 * lpfc_idiag_drbacc_write - Syntax check and set up idiag drbacc commands
4560 * @file: The file pointer to read from.
4561 * @buf: The buffer to copy the user data from.
4562 * @nbytes: The number of bytes to get.
4563 * @ppos: The position in the file to start reading from.
4564 *
4565 * This routine get the debugfs idiag command struct from user space and then
4566 * perform the syntax check for port doorbell register read (dump) or write
4567 * (set) command accordingly. In the case of port queue read command, it sets
4568 * up the command in the idiag command struct for the following debugfs read
4569 * operation. In the case of port doorbell register write operation, it
4570 * executes the write operation into the port doorbell register accordingly.
4571 *
4572 * It returns the @nbytges passing in from debugfs user space when successful.
4573 * In case of error conditions, it returns proper error code back to the user
4574 * space.
4575 **/
4576static ssize_t
4577lpfc_idiag_drbacc_write(struct file *file, const char __user *buf,
4578 size_t nbytes, loff_t *ppos)
4579{
4580 struct lpfc_debug *debug = file->private_data;
4581 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
James Smartb76f2dc2011-07-22 18:37:42 -04004582 uint32_t drb_reg_id, value, reg_val = 0;
James Smart86a80842011-04-16 11:03:04 -04004583 void __iomem *drb_reg;
4584 int rc;
4585
4586 /* This is a user write operation */
4587 debug->op = LPFC_IDIAG_OP_WR;
4588
4589 rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
4590 if (rc < 0)
4591 return rc;
4592
4593 /* Sanity check on command line arguments */
James Smartb76f2dc2011-07-22 18:37:42 -04004594 drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX];
4595 value = idiag.cmd.data[IDIAG_DRBACC_VALUE_INDX];
James Smart86a80842011-04-16 11:03:04 -04004596
4597 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR ||
4598 idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST ||
4599 idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) {
4600 if (rc != LPFC_DRB_ACC_WR_CMD_ARG)
4601 goto error_out;
4602 if (drb_reg_id > LPFC_DRB_MAX)
4603 goto error_out;
4604 } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD) {
4605 if (rc != LPFC_DRB_ACC_RD_CMD_ARG)
4606 goto error_out;
4607 if ((drb_reg_id > LPFC_DRB_MAX) &&
4608 (drb_reg_id != LPFC_DRB_ACC_ALL))
4609 goto error_out;
4610 } else
4611 goto error_out;
4612
4613 /* Perform the write access operation */
4614 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR ||
4615 idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST ||
4616 idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) {
4617 switch (drb_reg_id) {
James Smart9dd35422018-02-22 08:18:41 -08004618 case LPFC_DRB_EQ:
4619 drb_reg = phba->sli4_hba.EQDBregaddr;
4620 break;
4621 case LPFC_DRB_CQ:
4622 drb_reg = phba->sli4_hba.CQDBregaddr;
James Smart86a80842011-04-16 11:03:04 -04004623 break;
4624 case LPFC_DRB_MQ:
4625 drb_reg = phba->sli4_hba.MQDBregaddr;
4626 break;
4627 case LPFC_DRB_WQ:
4628 drb_reg = phba->sli4_hba.WQDBregaddr;
4629 break;
4630 case LPFC_DRB_RQ:
4631 drb_reg = phba->sli4_hba.RQDBregaddr;
4632 break;
4633 default:
4634 goto error_out;
4635 }
4636
4637 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR)
4638 reg_val = value;
4639 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST) {
4640 reg_val = readl(drb_reg);
4641 reg_val |= value;
4642 }
4643 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) {
4644 reg_val = readl(drb_reg);
4645 reg_val &= ~value;
4646 }
4647 writel(reg_val, drb_reg);
4648 readl(drb_reg); /* flush */
4649 }
4650 return nbytes;
4651
4652error_out:
4653 /* Clean out command structure on command error out */
4654 memset(&idiag, 0, sizeof(idiag));
4655 return -EINVAL;
4656}
4657
James Smartb76f2dc2011-07-22 18:37:42 -04004658/**
4659 * lpfc_idiag_ctlacc_read_reg - idiag debugfs read a control registers
4660 * @phba: The pointer to hba structure.
4661 * @pbuffer: The pointer to the buffer to copy the data to.
Matteo Croce92684bf2019-01-04 22:38:54 +01004662 * @len: The length of bytes to copied.
James Smartb76f2dc2011-07-22 18:37:42 -04004663 * @drbregid: The id to doorbell registers.
4664 *
4665 * Description:
4666 * This routine reads a control register and copies its content to the
4667 * user buffer pointed to by @pbuffer.
4668 *
4669 * Returns:
4670 * This function returns the amount of data that was copied into @pbuffer.
4671 **/
4672static int
4673lpfc_idiag_ctlacc_read_reg(struct lpfc_hba *phba, char *pbuffer,
4674 int len, uint32_t ctlregid)
4675{
4676
4677 if (!pbuffer)
4678 return 0;
4679
4680 switch (ctlregid) {
4681 case LPFC_CTL_PORT_SEM:
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004682 len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04004683 "Port SemReg: 0x%08x\n",
4684 readl(phba->sli4_hba.conf_regs_memmap_p +
4685 LPFC_CTL_PORT_SEM_OFFSET));
4686 break;
4687 case LPFC_CTL_PORT_STA:
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004688 len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04004689 "Port StaReg: 0x%08x\n",
4690 readl(phba->sli4_hba.conf_regs_memmap_p +
4691 LPFC_CTL_PORT_STA_OFFSET));
4692 break;
4693 case LPFC_CTL_PORT_CTL:
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004694 len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04004695 "Port CtlReg: 0x%08x\n",
4696 readl(phba->sli4_hba.conf_regs_memmap_p +
4697 LPFC_CTL_PORT_CTL_OFFSET));
4698 break;
4699 case LPFC_CTL_PORT_ER1:
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004700 len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04004701 "Port Er1Reg: 0x%08x\n",
4702 readl(phba->sli4_hba.conf_regs_memmap_p +
4703 LPFC_CTL_PORT_ER1_OFFSET));
4704 break;
4705 case LPFC_CTL_PORT_ER2:
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004706 len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04004707 "Port Er2Reg: 0x%08x\n",
4708 readl(phba->sli4_hba.conf_regs_memmap_p +
4709 LPFC_CTL_PORT_ER2_OFFSET));
4710 break;
4711 case LPFC_CTL_PDEV_CTL:
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004712 len += scnprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04004713 "PDev CtlReg: 0x%08x\n",
4714 readl(phba->sli4_hba.conf_regs_memmap_p +
4715 LPFC_CTL_PDEV_CTL_OFFSET));
4716 break;
4717 default:
4718 break;
4719 }
4720 return len;
4721}
4722
4723/**
4724 * lpfc_idiag_ctlacc_read - idiag debugfs read port and device control register
4725 * @file: The file pointer to read from.
4726 * @buf: The buffer to copy the data to.
4727 * @nbytes: The number of bytes to read.
4728 * @ppos: The position in the file to start reading from.
4729 *
4730 * Description:
4731 * This routine reads data from the @phba port and device registers according
4732 * to the idiag command, and copies to user @buf.
4733 *
4734 * Returns:
4735 * This function returns the amount of data that was read (this could be less
4736 * than @nbytes if the end of the file was reached) or a negative error value.
4737 **/
4738static ssize_t
4739lpfc_idiag_ctlacc_read(struct file *file, char __user *buf, size_t nbytes,
4740 loff_t *ppos)
4741{
4742 struct lpfc_debug *debug = file->private_data;
4743 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
4744 uint32_t ctl_reg_id, i;
4745 char *pbuffer;
4746 int len = 0;
4747
4748 /* This is a user read operation */
4749 debug->op = LPFC_IDIAG_OP_RD;
4750
4751 if (!debug->buffer)
4752 debug->buffer = kmalloc(LPFC_CTL_ACC_BUF_SIZE, GFP_KERNEL);
4753 if (!debug->buffer)
4754 return 0;
4755 pbuffer = debug->buffer;
4756
4757 if (*ppos)
4758 return 0;
4759
4760 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD)
4761 ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX];
4762 else
4763 return 0;
4764
4765 if (ctl_reg_id == LPFC_CTL_ACC_ALL)
4766 for (i = 1; i <= LPFC_CTL_MAX; i++)
4767 len = lpfc_idiag_ctlacc_read_reg(phba,
4768 pbuffer, len, i);
4769 else
4770 len = lpfc_idiag_ctlacc_read_reg(phba,
4771 pbuffer, len, ctl_reg_id);
4772
4773 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
4774}
4775
4776/**
4777 * lpfc_idiag_ctlacc_write - Syntax check and set up idiag ctlacc commands
4778 * @file: The file pointer to read from.
4779 * @buf: The buffer to copy the user data from.
4780 * @nbytes: The number of bytes to get.
4781 * @ppos: The position in the file to start reading from.
4782 *
4783 * This routine get the debugfs idiag command struct from user space and then
4784 * perform the syntax check for port and device control register read (dump)
4785 * or write (set) command accordingly.
4786 *
4787 * It returns the @nbytges passing in from debugfs user space when successful.
4788 * In case of error conditions, it returns proper error code back to the user
4789 * space.
4790 **/
4791static ssize_t
4792lpfc_idiag_ctlacc_write(struct file *file, const char __user *buf,
4793 size_t nbytes, loff_t *ppos)
4794{
4795 struct lpfc_debug *debug = file->private_data;
4796 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
4797 uint32_t ctl_reg_id, value, reg_val = 0;
4798 void __iomem *ctl_reg;
4799 int rc;
4800
4801 /* This is a user write operation */
4802 debug->op = LPFC_IDIAG_OP_WR;
4803
4804 rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
4805 if (rc < 0)
4806 return rc;
4807
4808 /* Sanity check on command line arguments */
4809 ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX];
4810 value = idiag.cmd.data[IDIAG_CTLACC_VALUE_INDX];
4811
4812 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR ||
4813 idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST ||
4814 idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
4815 if (rc != LPFC_CTL_ACC_WR_CMD_ARG)
4816 goto error_out;
4817 if (ctl_reg_id > LPFC_CTL_MAX)
4818 goto error_out;
4819 } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD) {
4820 if (rc != LPFC_CTL_ACC_RD_CMD_ARG)
4821 goto error_out;
4822 if ((ctl_reg_id > LPFC_CTL_MAX) &&
4823 (ctl_reg_id != LPFC_CTL_ACC_ALL))
4824 goto error_out;
4825 } else
4826 goto error_out;
4827
4828 /* Perform the write access operation */
4829 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR ||
4830 idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST ||
4831 idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
4832 switch (ctl_reg_id) {
4833 case LPFC_CTL_PORT_SEM:
4834 ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
4835 LPFC_CTL_PORT_SEM_OFFSET;
4836 break;
4837 case LPFC_CTL_PORT_STA:
4838 ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
4839 LPFC_CTL_PORT_STA_OFFSET;
4840 break;
4841 case LPFC_CTL_PORT_CTL:
4842 ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
4843 LPFC_CTL_PORT_CTL_OFFSET;
4844 break;
4845 case LPFC_CTL_PORT_ER1:
4846 ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
4847 LPFC_CTL_PORT_ER1_OFFSET;
4848 break;
4849 case LPFC_CTL_PORT_ER2:
4850 ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
4851 LPFC_CTL_PORT_ER2_OFFSET;
4852 break;
4853 case LPFC_CTL_PDEV_CTL:
4854 ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
4855 LPFC_CTL_PDEV_CTL_OFFSET;
4856 break;
4857 default:
4858 goto error_out;
4859 }
4860
4861 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR)
4862 reg_val = value;
4863 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST) {
4864 reg_val = readl(ctl_reg);
4865 reg_val |= value;
4866 }
4867 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
4868 reg_val = readl(ctl_reg);
4869 reg_val &= ~value;
4870 }
4871 writel(reg_val, ctl_reg);
4872 readl(ctl_reg); /* flush */
4873 }
4874 return nbytes;
4875
4876error_out:
4877 /* Clean out command structure on command error out */
4878 memset(&idiag, 0, sizeof(idiag));
4879 return -EINVAL;
4880}
4881
4882/**
4883 * lpfc_idiag_mbxacc_get_setup - idiag debugfs get mailbox access setup
4884 * @phba: Pointer to HBA context object.
4885 * @pbuffer: Pointer to data buffer.
4886 *
4887 * Description:
4888 * This routine gets the driver mailbox access debugfs setup information.
4889 *
4890 * Returns:
4891 * This function returns the amount of data that was read (this could be less
4892 * than @nbytes if the end of the file was reached) or a negative error value.
4893 **/
4894static int
4895lpfc_idiag_mbxacc_get_setup(struct lpfc_hba *phba, char *pbuffer)
4896{
4897 uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd;
4898 int len = 0;
4899
4900 mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
4901 mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
4902 mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
4903 mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
4904
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004905 len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04004906 "mbx_dump_map: 0x%08x\n", mbx_dump_map);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004907 len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04004908 "mbx_dump_cnt: %04d\n", mbx_dump_cnt);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004909 len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04004910 "mbx_word_cnt: %04d\n", mbx_word_cnt);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07004911 len += scnprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04004912 "mbx_mbox_cmd: 0x%02x\n", mbx_mbox_cmd);
4913
4914 return len;
4915}
4916
4917/**
4918 * lpfc_idiag_mbxacc_read - idiag debugfs read on mailbox access
4919 * @file: The file pointer to read from.
4920 * @buf: The buffer to copy the data to.
4921 * @nbytes: The number of bytes to read.
4922 * @ppos: The position in the file to start reading from.
4923 *
4924 * Description:
4925 * This routine reads data from the @phba driver mailbox access debugfs setup
4926 * information.
4927 *
4928 * Returns:
4929 * This function returns the amount of data that was read (this could be less
4930 * than @nbytes if the end of the file was reached) or a negative error value.
4931 **/
4932static ssize_t
4933lpfc_idiag_mbxacc_read(struct file *file, char __user *buf, size_t nbytes,
4934 loff_t *ppos)
4935{
4936 struct lpfc_debug *debug = file->private_data;
4937 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
4938 char *pbuffer;
4939 int len = 0;
4940
4941 /* This is a user read operation */
4942 debug->op = LPFC_IDIAG_OP_RD;
4943
4944 if (!debug->buffer)
4945 debug->buffer = kmalloc(LPFC_MBX_ACC_BUF_SIZE, GFP_KERNEL);
4946 if (!debug->buffer)
4947 return 0;
4948 pbuffer = debug->buffer;
4949
4950 if (*ppos)
4951 return 0;
4952
4953 if ((idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP) &&
4954 (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP))
4955 return 0;
4956
4957 len = lpfc_idiag_mbxacc_get_setup(phba, pbuffer);
4958
4959 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
4960}
4961
4962/**
4963 * lpfc_idiag_mbxacc_write - Syntax check and set up idiag mbxacc commands
4964 * @file: The file pointer to read from.
4965 * @buf: The buffer to copy the user data from.
4966 * @nbytes: The number of bytes to get.
4967 * @ppos: The position in the file to start reading from.
4968 *
4969 * This routine get the debugfs idiag command struct from user space and then
4970 * perform the syntax check for driver mailbox command (dump) and sets up the
4971 * necessary states in the idiag command struct accordingly.
4972 *
4973 * It returns the @nbytges passing in from debugfs user space when successful.
4974 * In case of error conditions, it returns proper error code back to the user
4975 * space.
4976 **/
4977static ssize_t
4978lpfc_idiag_mbxacc_write(struct file *file, const char __user *buf,
4979 size_t nbytes, loff_t *ppos)
4980{
4981 struct lpfc_debug *debug = file->private_data;
4982 uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd;
4983 int rc;
4984
4985 /* This is a user write operation */
4986 debug->op = LPFC_IDIAG_OP_WR;
4987
4988 rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
4989 if (rc < 0)
4990 return rc;
4991
4992 /* Sanity check on command line arguments */
4993 mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
4994 mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
4995 mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
4996 mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
4997
4998 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_MBXACC_DP) {
4999 if (!(mbx_dump_map & LPFC_MBX_DMP_MBX_ALL))
5000 goto error_out;
5001 if ((mbx_dump_map & ~LPFC_MBX_DMP_MBX_ALL) &&
5002 (mbx_dump_map != LPFC_MBX_DMP_ALL))
5003 goto error_out;
5004 if (mbx_word_cnt > sizeof(MAILBOX_t))
5005 goto error_out;
5006 } else if (idiag.cmd.opcode == LPFC_IDIAG_BSG_MBXACC_DP) {
5007 if (!(mbx_dump_map & LPFC_BSG_DMP_MBX_ALL))
5008 goto error_out;
5009 if ((mbx_dump_map & ~LPFC_BSG_DMP_MBX_ALL) &&
5010 (mbx_dump_map != LPFC_MBX_DMP_ALL))
5011 goto error_out;
5012 if (mbx_word_cnt > (BSG_MBOX_SIZE)/4)
5013 goto error_out;
5014 if (mbx_mbox_cmd != 0x9b)
5015 goto error_out;
5016 } else
5017 goto error_out;
5018
5019 if (mbx_word_cnt == 0)
5020 goto error_out;
5021 if (rc != LPFC_MBX_DMP_ARG)
5022 goto error_out;
5023 if (mbx_mbox_cmd & ~0xff)
5024 goto error_out;
5025
5026 /* condition for stop mailbox dump */
5027 if (mbx_dump_cnt == 0)
5028 goto reset_out;
5029
5030 return nbytes;
5031
5032reset_out:
5033 /* Clean out command structure on command error out */
5034 memset(&idiag, 0, sizeof(idiag));
5035 return nbytes;
5036
5037error_out:
5038 /* Clean out command structure on command error out */
5039 memset(&idiag, 0, sizeof(idiag));
5040 return -EINVAL;
5041}
5042
5043/**
5044 * lpfc_idiag_extacc_avail_get - get the available extents information
5045 * @phba: pointer to lpfc hba data structure.
5046 * @pbuffer: pointer to internal buffer.
5047 * @len: length into the internal buffer data has been copied.
5048 *
5049 * Description:
5050 * This routine is to get the available extent information.
5051 *
5052 * Returns:
5053 * overall lenth of the data read into the internal buffer.
5054 **/
5055static int
5056lpfc_idiag_extacc_avail_get(struct lpfc_hba *phba, char *pbuffer, int len)
5057{
5058 uint16_t ext_cnt, ext_size;
5059
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005060 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005061 "\nAvailable Extents Information:\n");
5062
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005063 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005064 "\tPort Available VPI extents: ");
5065 lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VPI,
5066 &ext_cnt, &ext_size);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005067 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005068 "Count %3d, Size %3d\n", ext_cnt, ext_size);
5069
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005070 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005071 "\tPort Available VFI extents: ");
5072 lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VFI,
5073 &ext_cnt, &ext_size);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005074 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005075 "Count %3d, Size %3d\n", ext_cnt, ext_size);
5076
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005077 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005078 "\tPort Available RPI extents: ");
5079 lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_RPI,
5080 &ext_cnt, &ext_size);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005081 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005082 "Count %3d, Size %3d\n", ext_cnt, ext_size);
5083
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005084 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005085 "\tPort Available XRI extents: ");
5086 lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_XRI,
5087 &ext_cnt, &ext_size);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005088 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005089 "Count %3d, Size %3d\n", ext_cnt, ext_size);
5090
5091 return len;
5092}
5093
5094/**
5095 * lpfc_idiag_extacc_alloc_get - get the allocated extents information
5096 * @phba: pointer to lpfc hba data structure.
5097 * @pbuffer: pointer to internal buffer.
5098 * @len: length into the internal buffer data has been copied.
5099 *
5100 * Description:
5101 * This routine is to get the allocated extent information.
5102 *
5103 * Returns:
5104 * overall lenth of the data read into the internal buffer.
5105 **/
5106static int
5107lpfc_idiag_extacc_alloc_get(struct lpfc_hba *phba, char *pbuffer, int len)
5108{
5109 uint16_t ext_cnt, ext_size;
5110 int rc;
5111
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005112 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005113 "\nAllocated Extents Information:\n");
5114
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005115 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005116 "\tHost Allocated VPI extents: ");
5117 rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VPI,
5118 &ext_cnt, &ext_size);
5119 if (!rc)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005120 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005121 "Port %d Extent %3d, Size %3d\n",
5122 phba->brd_no, ext_cnt, ext_size);
5123 else
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005124 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005125 "N/A\n");
5126
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005127 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005128 "\tHost Allocated VFI extents: ");
5129 rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VFI,
5130 &ext_cnt, &ext_size);
5131 if (!rc)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005132 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005133 "Port %d Extent %3d, Size %3d\n",
5134 phba->brd_no, ext_cnt, ext_size);
5135 else
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005136 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005137 "N/A\n");
5138
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005139 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005140 "\tHost Allocated RPI extents: ");
5141 rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_RPI,
5142 &ext_cnt, &ext_size);
5143 if (!rc)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005144 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005145 "Port %d Extent %3d, Size %3d\n",
5146 phba->brd_no, ext_cnt, ext_size);
5147 else
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005148 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005149 "N/A\n");
5150
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005151 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005152 "\tHost Allocated XRI extents: ");
5153 rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_XRI,
5154 &ext_cnt, &ext_size);
5155 if (!rc)
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005156 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005157 "Port %d Extent %3d, Size %3d\n",
5158 phba->brd_no, ext_cnt, ext_size);
5159 else
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005160 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005161 "N/A\n");
5162
5163 return len;
5164}
5165
5166/**
5167 * lpfc_idiag_extacc_drivr_get - get driver extent information
5168 * @phba: pointer to lpfc hba data structure.
5169 * @pbuffer: pointer to internal buffer.
5170 * @len: length into the internal buffer data has been copied.
5171 *
5172 * Description:
5173 * This routine is to get the driver extent information.
5174 *
5175 * Returns:
5176 * overall lenth of the data read into the internal buffer.
5177 **/
5178static int
5179lpfc_idiag_extacc_drivr_get(struct lpfc_hba *phba, char *pbuffer, int len)
5180{
5181 struct lpfc_rsrc_blks *rsrc_blks;
5182 int index;
5183
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005184 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005185 "\nDriver Extents Information:\n");
5186
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005187 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005188 "\tVPI extents:\n");
5189 index = 0;
5190 list_for_each_entry(rsrc_blks, &phba->lpfc_vpi_blk_list, list) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005191 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005192 "\t\tBlock %3d: Start %4d, Count %4d\n",
5193 index, rsrc_blks->rsrc_start,
5194 rsrc_blks->rsrc_size);
5195 index++;
5196 }
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005197 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005198 "\tVFI extents:\n");
5199 index = 0;
5200 list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_vfi_blk_list,
5201 list) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005202 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005203 "\t\tBlock %3d: Start %4d, Count %4d\n",
5204 index, rsrc_blks->rsrc_start,
5205 rsrc_blks->rsrc_size);
5206 index++;
5207 }
5208
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005209 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005210 "\tRPI extents:\n");
5211 index = 0;
5212 list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_rpi_blk_list,
5213 list) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005214 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005215 "\t\tBlock %3d: Start %4d, Count %4d\n",
5216 index, rsrc_blks->rsrc_start,
5217 rsrc_blks->rsrc_size);
5218 index++;
5219 }
5220
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005221 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005222 "\tXRI extents:\n");
5223 index = 0;
5224 list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_xri_blk_list,
5225 list) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005226 len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005227 "\t\tBlock %3d: Start %4d, Count %4d\n",
5228 index, rsrc_blks->rsrc_start,
5229 rsrc_blks->rsrc_size);
5230 index++;
5231 }
5232
5233 return len;
5234}
5235
5236/**
5237 * lpfc_idiag_extacc_write - Syntax check and set up idiag extacc commands
5238 * @file: The file pointer to read from.
5239 * @buf: The buffer to copy the user data from.
5240 * @nbytes: The number of bytes to get.
5241 * @ppos: The position in the file to start reading from.
5242 *
5243 * This routine get the debugfs idiag command struct from user space and then
5244 * perform the syntax check for extent information access commands and sets
5245 * up the necessary states in the idiag command struct accordingly.
5246 *
5247 * It returns the @nbytges passing in from debugfs user space when successful.
5248 * In case of error conditions, it returns proper error code back to the user
5249 * space.
5250 **/
5251static ssize_t
5252lpfc_idiag_extacc_write(struct file *file, const char __user *buf,
5253 size_t nbytes, loff_t *ppos)
5254{
5255 struct lpfc_debug *debug = file->private_data;
5256 uint32_t ext_map;
5257 int rc;
5258
5259 /* This is a user write operation */
5260 debug->op = LPFC_IDIAG_OP_WR;
5261
5262 rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
5263 if (rc < 0)
5264 return rc;
5265
5266 ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX];
5267
5268 if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD)
5269 goto error_out;
5270 if (rc != LPFC_EXT_ACC_CMD_ARG)
5271 goto error_out;
5272 if (!(ext_map & LPFC_EXT_ACC_ALL))
5273 goto error_out;
5274
5275 return nbytes;
5276error_out:
5277 /* Clean out command structure on command error out */
5278 memset(&idiag, 0, sizeof(idiag));
5279 return -EINVAL;
5280}
5281
5282/**
5283 * lpfc_idiag_extacc_read - idiag debugfs read access to extent information
5284 * @file: The file pointer to read from.
5285 * @buf: The buffer to copy the data to.
5286 * @nbytes: The number of bytes to read.
5287 * @ppos: The position in the file to start reading from.
5288 *
5289 * Description:
5290 * This routine reads data from the proper extent information according to
5291 * the idiag command, and copies to user @buf.
5292 *
5293 * Returns:
5294 * This function returns the amount of data that was read (this could be less
5295 * than @nbytes if the end of the file was reached) or a negative error value.
5296 **/
5297static ssize_t
5298lpfc_idiag_extacc_read(struct file *file, char __user *buf, size_t nbytes,
5299 loff_t *ppos)
5300{
5301 struct lpfc_debug *debug = file->private_data;
5302 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
5303 char *pbuffer;
5304 uint32_t ext_map;
5305 int len = 0;
5306
5307 /* This is a user read operation */
5308 debug->op = LPFC_IDIAG_OP_RD;
5309
5310 if (!debug->buffer)
5311 debug->buffer = kmalloc(LPFC_EXT_ACC_BUF_SIZE, GFP_KERNEL);
5312 if (!debug->buffer)
5313 return 0;
5314 pbuffer = debug->buffer;
5315 if (*ppos)
5316 return 0;
5317 if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD)
5318 return 0;
5319
5320 ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX];
5321 if (ext_map & LPFC_EXT_ACC_AVAIL)
5322 len = lpfc_idiag_extacc_avail_get(phba, pbuffer, len);
5323 if (ext_map & LPFC_EXT_ACC_ALLOC)
5324 len = lpfc_idiag_extacc_alloc_get(phba, pbuffer, len);
5325 if (ext_map & LPFC_EXT_ACC_DRIVR)
5326 len = lpfc_idiag_extacc_drivr_get(phba, pbuffer, len);
5327
5328 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
5329}
5330
James Smart858c9f62007-06-17 19:56:39 -05005331#undef lpfc_debugfs_op_disc_trc
Jan Engelhardt71fa7422009-01-11 10:38:59 +01005332static const struct file_operations lpfc_debugfs_op_disc_trc = {
James Smart858c9f62007-06-17 19:56:39 -05005333 .owner = THIS_MODULE,
5334 .open = lpfc_debugfs_disc_trc_open,
5335 .llseek = lpfc_debugfs_lseek,
5336 .read = lpfc_debugfs_read,
5337 .release = lpfc_debugfs_release,
5338};
5339
5340#undef lpfc_debugfs_op_nodelist
Jan Engelhardt71fa7422009-01-11 10:38:59 +01005341static const struct file_operations lpfc_debugfs_op_nodelist = {
James Smart858c9f62007-06-17 19:56:39 -05005342 .owner = THIS_MODULE,
5343 .open = lpfc_debugfs_nodelist_open,
5344 .llseek = lpfc_debugfs_lseek,
5345 .read = lpfc_debugfs_read,
5346 .release = lpfc_debugfs_release,
5347};
5348
James Smartc4908502019-01-28 11:14:28 -08005349#undef lpfc_debugfs_op_multixripools
5350static const struct file_operations lpfc_debugfs_op_multixripools = {
5351 .owner = THIS_MODULE,
5352 .open = lpfc_debugfs_multixripools_open,
5353 .llseek = lpfc_debugfs_lseek,
5354 .read = lpfc_debugfs_read,
5355 .write = lpfc_debugfs_multixripools_write,
5356 .release = lpfc_debugfs_release,
5357};
5358
James Smart78b2d852007-08-02 11:10:21 -04005359#undef lpfc_debugfs_op_hbqinfo
Jan Engelhardt71fa7422009-01-11 10:38:59 +01005360static const struct file_operations lpfc_debugfs_op_hbqinfo = {
James Smart78b2d852007-08-02 11:10:21 -04005361 .owner = THIS_MODULE,
5362 .open = lpfc_debugfs_hbqinfo_open,
5363 .llseek = lpfc_debugfs_lseek,
5364 .read = lpfc_debugfs_read,
5365 .release = lpfc_debugfs_release,
5366};
5367
James Smart6a828b02019-01-28 11:14:31 -08005368#ifdef LPFC_HDWQ_LOCK_STAT
5369#undef lpfc_debugfs_op_lockstat
5370static const struct file_operations lpfc_debugfs_op_lockstat = {
James Smart5e5b5112019-01-28 11:14:22 -08005371 .owner = THIS_MODULE,
James Smart6a828b02019-01-28 11:14:31 -08005372 .open = lpfc_debugfs_lockstat_open,
James Smart5e5b5112019-01-28 11:14:22 -08005373 .llseek = lpfc_debugfs_lseek,
5374 .read = lpfc_debugfs_read,
James Smart6a828b02019-01-28 11:14:31 -08005375 .write = lpfc_debugfs_lockstat_write,
James Smart5e5b5112019-01-28 11:14:22 -08005376 .release = lpfc_debugfs_release,
5377};
James Smart6a828b02019-01-28 11:14:31 -08005378#endif
James Smart5e5b5112019-01-28 11:14:22 -08005379
James Smart95bfc6d2019-10-18 14:18:27 -07005380#undef lpfc_debugfs_ras_log
5381static const struct file_operations lpfc_debugfs_ras_log = {
5382 .owner = THIS_MODULE,
5383 .open = lpfc_debugfs_ras_log_open,
5384 .llseek = lpfc_debugfs_lseek,
5385 .read = lpfc_debugfs_read,
5386 .release = lpfc_debugfs_ras_log_release,
5387};
5388#endif
5389
James Smartc95d6c62008-01-11 01:53:23 -05005390#undef lpfc_debugfs_op_dumpHBASlim
Jan Engelhardt71fa7422009-01-11 10:38:59 +01005391static const struct file_operations lpfc_debugfs_op_dumpHBASlim = {
James Smarta58cbd52007-08-02 11:09:43 -04005392 .owner = THIS_MODULE,
James Smartc95d6c62008-01-11 01:53:23 -05005393 .open = lpfc_debugfs_dumpHBASlim_open,
5394 .llseek = lpfc_debugfs_lseek,
5395 .read = lpfc_debugfs_read,
5396 .release = lpfc_debugfs_release,
5397};
5398
5399#undef lpfc_debugfs_op_dumpHostSlim
Jan Engelhardt71fa7422009-01-11 10:38:59 +01005400static const struct file_operations lpfc_debugfs_op_dumpHostSlim = {
James Smartc95d6c62008-01-11 01:53:23 -05005401 .owner = THIS_MODULE,
5402 .open = lpfc_debugfs_dumpHostSlim_open,
James Smarta58cbd52007-08-02 11:09:43 -04005403 .llseek = lpfc_debugfs_lseek,
5404 .read = lpfc_debugfs_read,
5405 .release = lpfc_debugfs_release,
5406};
5407
James Smartbd2cdd52017-02-12 13:52:33 -08005408#undef lpfc_debugfs_op_nvmestat
5409static const struct file_operations lpfc_debugfs_op_nvmestat = {
5410 .owner = THIS_MODULE,
5411 .open = lpfc_debugfs_nvmestat_open,
5412 .llseek = lpfc_debugfs_lseek,
5413 .read = lpfc_debugfs_read,
James Smart2b65e182017-02-12 13:52:38 -08005414 .write = lpfc_debugfs_nvmestat_write,
James Smartbd2cdd52017-02-12 13:52:33 -08005415 .release = lpfc_debugfs_release,
5416};
5417
James Smart4c47efc2019-01-28 11:14:25 -08005418#undef lpfc_debugfs_op_scsistat
5419static const struct file_operations lpfc_debugfs_op_scsistat = {
5420 .owner = THIS_MODULE,
5421 .open = lpfc_debugfs_scsistat_open,
5422 .llseek = lpfc_debugfs_lseek,
5423 .read = lpfc_debugfs_read,
5424 .write = lpfc_debugfs_scsistat_write,
5425 .release = lpfc_debugfs_release,
5426};
5427
James Smartbd2cdd52017-02-12 13:52:33 -08005428#undef lpfc_debugfs_op_nvmektime
5429static const struct file_operations lpfc_debugfs_op_nvmektime = {
5430 .owner = THIS_MODULE,
5431 .open = lpfc_debugfs_nvmektime_open,
5432 .llseek = lpfc_debugfs_lseek,
5433 .read = lpfc_debugfs_read,
5434 .write = lpfc_debugfs_nvmektime_write,
5435 .release = lpfc_debugfs_release,
5436};
5437
5438#undef lpfc_debugfs_op_nvmeio_trc
5439static const struct file_operations lpfc_debugfs_op_nvmeio_trc = {
5440 .owner = THIS_MODULE,
5441 .open = lpfc_debugfs_nvmeio_trc_open,
5442 .llseek = lpfc_debugfs_lseek,
5443 .read = lpfc_debugfs_read,
5444 .write = lpfc_debugfs_nvmeio_trc_write,
5445 .release = lpfc_debugfs_release,
5446};
5447
5448#undef lpfc_debugfs_op_cpucheck
5449static const struct file_operations lpfc_debugfs_op_cpucheck = {
5450 .owner = THIS_MODULE,
5451 .open = lpfc_debugfs_cpucheck_open,
5452 .llseek = lpfc_debugfs_lseek,
5453 .read = lpfc_debugfs_read,
5454 .write = lpfc_debugfs_cpucheck_write,
5455 .release = lpfc_debugfs_release,
5456};
5457
James Smartf9bb2da2011-10-10 21:34:11 -04005458#undef lpfc_debugfs_op_dif_err
5459static const struct file_operations lpfc_debugfs_op_dif_err = {
5460 .owner = THIS_MODULE,
Stephen Boyd234e3402012-04-05 14:25:11 -07005461 .open = simple_open,
James Smartf9bb2da2011-10-10 21:34:11 -04005462 .llseek = lpfc_debugfs_lseek,
5463 .read = lpfc_debugfs_dif_err_read,
5464 .write = lpfc_debugfs_dif_err_write,
5465 .release = lpfc_debugfs_dif_err_release,
5466};
5467
James Smarta58cbd52007-08-02 11:09:43 -04005468#undef lpfc_debugfs_op_slow_ring_trc
Jan Engelhardt71fa7422009-01-11 10:38:59 +01005469static const struct file_operations lpfc_debugfs_op_slow_ring_trc = {
James Smarta58cbd52007-08-02 11:09:43 -04005470 .owner = THIS_MODULE,
5471 .open = lpfc_debugfs_slow_ring_trc_open,
5472 .llseek = lpfc_debugfs_lseek,
5473 .read = lpfc_debugfs_read,
5474 .release = lpfc_debugfs_release,
5475};
5476
James Smart858c9f62007-06-17 19:56:39 -05005477static struct dentry *lpfc_debugfs_root = NULL;
5478static atomic_t lpfc_debugfs_hba_count;
James Smart2a622bf2011-02-16 12:40:06 -05005479
5480/*
5481 * File operations for the iDiag debugfs
5482 */
5483#undef lpfc_idiag_op_pciCfg
5484static const struct file_operations lpfc_idiag_op_pciCfg = {
5485 .owner = THIS_MODULE,
5486 .open = lpfc_idiag_open,
5487 .llseek = lpfc_debugfs_lseek,
5488 .read = lpfc_idiag_pcicfg_read,
5489 .write = lpfc_idiag_pcicfg_write,
5490 .release = lpfc_idiag_cmd_release,
5491};
5492
James Smartb76f2dc2011-07-22 18:37:42 -04005493#undef lpfc_idiag_op_barAcc
5494static const struct file_operations lpfc_idiag_op_barAcc = {
5495 .owner = THIS_MODULE,
5496 .open = lpfc_idiag_open,
5497 .llseek = lpfc_debugfs_lseek,
5498 .read = lpfc_idiag_baracc_read,
5499 .write = lpfc_idiag_baracc_write,
5500 .release = lpfc_idiag_cmd_release,
5501};
5502
James Smart2a622bf2011-02-16 12:40:06 -05005503#undef lpfc_idiag_op_queInfo
5504static const struct file_operations lpfc_idiag_op_queInfo = {
5505 .owner = THIS_MODULE,
5506 .open = lpfc_idiag_open,
5507 .read = lpfc_idiag_queinfo_read,
5508 .release = lpfc_idiag_release,
5509};
5510
James Smartb76f2dc2011-07-22 18:37:42 -04005511#undef lpfc_idiag_op_queAcc
James Smart86a80842011-04-16 11:03:04 -04005512static const struct file_operations lpfc_idiag_op_queAcc = {
5513 .owner = THIS_MODULE,
5514 .open = lpfc_idiag_open,
5515 .llseek = lpfc_debugfs_lseek,
5516 .read = lpfc_idiag_queacc_read,
5517 .write = lpfc_idiag_queacc_write,
5518 .release = lpfc_idiag_cmd_release,
5519};
5520
James Smartb76f2dc2011-07-22 18:37:42 -04005521#undef lpfc_idiag_op_drbAcc
James Smart86a80842011-04-16 11:03:04 -04005522static const struct file_operations lpfc_idiag_op_drbAcc = {
5523 .owner = THIS_MODULE,
5524 .open = lpfc_idiag_open,
5525 .llseek = lpfc_debugfs_lseek,
5526 .read = lpfc_idiag_drbacc_read,
5527 .write = lpfc_idiag_drbacc_write,
5528 .release = lpfc_idiag_cmd_release,
5529};
5530
James Smartb76f2dc2011-07-22 18:37:42 -04005531#undef lpfc_idiag_op_ctlAcc
5532static const struct file_operations lpfc_idiag_op_ctlAcc = {
5533 .owner = THIS_MODULE,
5534 .open = lpfc_idiag_open,
5535 .llseek = lpfc_debugfs_lseek,
5536 .read = lpfc_idiag_ctlacc_read,
5537 .write = lpfc_idiag_ctlacc_write,
5538 .release = lpfc_idiag_cmd_release,
5539};
5540
5541#undef lpfc_idiag_op_mbxAcc
5542static const struct file_operations lpfc_idiag_op_mbxAcc = {
5543 .owner = THIS_MODULE,
5544 .open = lpfc_idiag_open,
5545 .llseek = lpfc_debugfs_lseek,
5546 .read = lpfc_idiag_mbxacc_read,
5547 .write = lpfc_idiag_mbxacc_write,
5548 .release = lpfc_idiag_cmd_release,
5549};
5550
5551#undef lpfc_idiag_op_extAcc
5552static const struct file_operations lpfc_idiag_op_extAcc = {
5553 .owner = THIS_MODULE,
5554 .open = lpfc_idiag_open,
5555 .llseek = lpfc_debugfs_lseek,
5556 .read = lpfc_idiag_extacc_read,
5557 .write = lpfc_idiag_extacc_write,
5558 .release = lpfc_idiag_cmd_release,
5559};
5560
James Smart858c9f62007-06-17 19:56:39 -05005561
James Smartb76f2dc2011-07-22 18:37:42 -04005562/* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command
5563 * @phba: Pointer to HBA context object.
5564 * @dmabuf: Pointer to a DMA buffer descriptor.
5565 *
5566 * Description:
5567 * This routine dump a bsg pass-through non-embedded mailbox command with
5568 * external buffer.
5569 **/
5570void
5571lpfc_idiag_mbxacc_dump_bsg_mbox(struct lpfc_hba *phba, enum nemb_type nemb_tp,
5572 enum mbox_type mbox_tp, enum dma_type dma_tp,
5573 enum sta_type sta_tp,
5574 struct lpfc_dmabuf *dmabuf, uint32_t ext_buf)
5575{
5576#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
5577 uint32_t *mbx_mbox_cmd, *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt;
5578 char line_buf[LPFC_MBX_ACC_LBUF_SZ];
5579 int len = 0;
5580 uint32_t do_dump = 0;
5581 uint32_t *pword;
5582 uint32_t i;
5583
5584 if (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP)
5585 return;
5586
5587 mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
5588 mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
5589 mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
5590 mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
5591
5592 if (!(*mbx_dump_map & LPFC_MBX_DMP_ALL) ||
5593 (*mbx_dump_cnt == 0) ||
5594 (*mbx_word_cnt == 0))
5595 return;
5596
5597 if (*mbx_mbox_cmd != 0x9B)
5598 return;
5599
5600 if ((mbox_tp == mbox_rd) && (dma_tp == dma_mbox)) {
5601 if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_MBX) {
5602 do_dump |= LPFC_BSG_DMP_MBX_RD_MBX;
James Smart2ea259e2017-02-12 13:52:27 -08005603 pr_err("\nRead mbox command (x%x), "
James Smartb76f2dc2011-07-22 18:37:42 -04005604 "nemb:0x%x, extbuf_cnt:%d:\n",
5605 sta_tp, nemb_tp, ext_buf);
5606 }
5607 }
5608 if ((mbox_tp == mbox_rd) && (dma_tp == dma_ebuf)) {
5609 if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_BUF) {
5610 do_dump |= LPFC_BSG_DMP_MBX_RD_BUF;
James Smart2ea259e2017-02-12 13:52:27 -08005611 pr_err("\nRead mbox buffer (x%x), "
James Smartb76f2dc2011-07-22 18:37:42 -04005612 "nemb:0x%x, extbuf_seq:%d:\n",
5613 sta_tp, nemb_tp, ext_buf);
5614 }
5615 }
5616 if ((mbox_tp == mbox_wr) && (dma_tp == dma_mbox)) {
5617 if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_MBX) {
5618 do_dump |= LPFC_BSG_DMP_MBX_WR_MBX;
James Smart2ea259e2017-02-12 13:52:27 -08005619 pr_err("\nWrite mbox command (x%x), "
James Smartb76f2dc2011-07-22 18:37:42 -04005620 "nemb:0x%x, extbuf_cnt:%d:\n",
5621 sta_tp, nemb_tp, ext_buf);
5622 }
5623 }
5624 if ((mbox_tp == mbox_wr) && (dma_tp == dma_ebuf)) {
5625 if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_BUF) {
5626 do_dump |= LPFC_BSG_DMP_MBX_WR_BUF;
James Smart2ea259e2017-02-12 13:52:27 -08005627 pr_err("\nWrite mbox buffer (x%x), "
James Smartb76f2dc2011-07-22 18:37:42 -04005628 "nemb:0x%x, extbuf_seq:%d:\n",
5629 sta_tp, nemb_tp, ext_buf);
5630 }
5631 }
5632
5633 /* dump buffer content */
5634 if (do_dump) {
5635 pword = (uint32_t *)dmabuf->virt;
5636 for (i = 0; i < *mbx_word_cnt; i++) {
5637 if (!(i % 8)) {
5638 if (i != 0)
James Smart2ea259e2017-02-12 13:52:27 -08005639 pr_err("%s\n", line_buf);
James Smartb76f2dc2011-07-22 18:37:42 -04005640 len = 0;
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005641 len += scnprintf(line_buf+len,
James Smartb76f2dc2011-07-22 18:37:42 -04005642 LPFC_MBX_ACC_LBUF_SZ-len,
5643 "%03d: ", i);
5644 }
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005645 len += scnprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005646 "%08x ", (uint32_t)*pword);
5647 pword++;
5648 }
5649 if ((i - 1) % 8)
James Smart2ea259e2017-02-12 13:52:27 -08005650 pr_err("%s\n", line_buf);
James Smartb76f2dc2011-07-22 18:37:42 -04005651 (*mbx_dump_cnt)--;
5652 }
5653
5654 /* Clean out command structure on reaching dump count */
5655 if (*mbx_dump_cnt == 0)
5656 memset(&idiag, 0, sizeof(idiag));
5657 return;
5658#endif
5659}
5660
5661/* lpfc_idiag_mbxacc_dump_issue_mbox - idiag debugfs dump issue mailbox command
5662 * @phba: Pointer to HBA context object.
5663 * @dmabuf: Pointer to a DMA buffer descriptor.
5664 *
5665 * Description:
5666 * This routine dump a pass-through non-embedded mailbox command from issue
5667 * mailbox command.
5668 **/
5669void
5670lpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *phba, MAILBOX_t *pmbox)
5671{
5672#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
5673 uint32_t *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt, *mbx_mbox_cmd;
5674 char line_buf[LPFC_MBX_ACC_LBUF_SZ];
5675 int len = 0;
5676 uint32_t *pword;
5677 uint8_t *pbyte;
5678 uint32_t i, j;
5679
5680 if (idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP)
5681 return;
5682
5683 mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
5684 mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
5685 mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
5686 mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
5687
5688 if (!(*mbx_dump_map & LPFC_MBX_DMP_MBX_ALL) ||
5689 (*mbx_dump_cnt == 0) ||
5690 (*mbx_word_cnt == 0))
5691 return;
5692
5693 if ((*mbx_mbox_cmd != LPFC_MBX_ALL_CMD) &&
5694 (*mbx_mbox_cmd != pmbox->mbxCommand))
5695 return;
5696
5697 /* dump buffer content */
5698 if (*mbx_dump_map & LPFC_MBX_DMP_MBX_WORD) {
James Smart2ea259e2017-02-12 13:52:27 -08005699 pr_err("Mailbox command:0x%x dump by word:\n",
James Smartb76f2dc2011-07-22 18:37:42 -04005700 pmbox->mbxCommand);
5701 pword = (uint32_t *)pmbox;
5702 for (i = 0; i < *mbx_word_cnt; i++) {
5703 if (!(i % 8)) {
5704 if (i != 0)
James Smart2ea259e2017-02-12 13:52:27 -08005705 pr_err("%s\n", line_buf);
James Smartb76f2dc2011-07-22 18:37:42 -04005706 len = 0;
5707 memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005708 len += scnprintf(line_buf+len,
James Smartb76f2dc2011-07-22 18:37:42 -04005709 LPFC_MBX_ACC_LBUF_SZ-len,
5710 "%03d: ", i);
5711 }
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005712 len += scnprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len,
James Smartb76f2dc2011-07-22 18:37:42 -04005713 "%08x ",
5714 ((uint32_t)*pword) & 0xffffffff);
5715 pword++;
5716 }
5717 if ((i - 1) % 8)
James Smart2ea259e2017-02-12 13:52:27 -08005718 pr_err("%s\n", line_buf);
5719 pr_err("\n");
James Smartb76f2dc2011-07-22 18:37:42 -04005720 }
5721 if (*mbx_dump_map & LPFC_MBX_DMP_MBX_BYTE) {
James Smart2ea259e2017-02-12 13:52:27 -08005722 pr_err("Mailbox command:0x%x dump by byte:\n",
James Smartb76f2dc2011-07-22 18:37:42 -04005723 pmbox->mbxCommand);
5724 pbyte = (uint8_t *)pmbox;
5725 for (i = 0; i < *mbx_word_cnt; i++) {
5726 if (!(i % 8)) {
5727 if (i != 0)
James Smart2ea259e2017-02-12 13:52:27 -08005728 pr_err("%s\n", line_buf);
James Smartb76f2dc2011-07-22 18:37:42 -04005729 len = 0;
5730 memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ);
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005731 len += scnprintf(line_buf+len,
James Smartb76f2dc2011-07-22 18:37:42 -04005732 LPFC_MBX_ACC_LBUF_SZ-len,
5733 "%03d: ", i);
5734 }
5735 for (j = 0; j < 4; j++) {
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005736 len += scnprintf(line_buf+len,
James Smartb76f2dc2011-07-22 18:37:42 -04005737 LPFC_MBX_ACC_LBUF_SZ-len,
5738 "%02x",
5739 ((uint8_t)*pbyte) & 0xff);
5740 pbyte++;
5741 }
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07005742 len += scnprintf(line_buf+len,
James Smartb76f2dc2011-07-22 18:37:42 -04005743 LPFC_MBX_ACC_LBUF_SZ-len, " ");
5744 }
5745 if ((i - 1) % 8)
James Smart2ea259e2017-02-12 13:52:27 -08005746 pr_err("%s\n", line_buf);
5747 pr_err("\n");
James Smartb76f2dc2011-07-22 18:37:42 -04005748 }
5749 (*mbx_dump_cnt)--;
5750
5751 /* Clean out command structure on reaching dump count */
5752 if (*mbx_dump_cnt == 0)
5753 memset(&idiag, 0, sizeof(idiag));
5754 return;
5755#endif
5756}
5757
James Smarte59058c2008-08-24 21:49:00 -04005758/**
James Smart3621a712009-04-06 18:47:14 -04005759 * lpfc_debugfs_initialize - Initialize debugfs for a vport
James Smarte59058c2008-08-24 21:49:00 -04005760 * @vport: The vport pointer to initialize.
5761 *
5762 * Description:
5763 * When Debugfs is configured this routine sets up the lpfc debugfs file system.
5764 * If not already created, this routine will create the lpfc directory, and
5765 * lpfcX directory (for this HBA), and vportX directory for this vport. It will
5766 * also create each file used to access lpfc specific debugfs information.
5767 **/
James Smart858c9f62007-06-17 19:56:39 -05005768inline void
5769lpfc_debugfs_initialize(struct lpfc_vport *vport)
5770{
James Smart923e4b62008-12-04 22:40:07 -05005771#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
James Smart858c9f62007-06-17 19:56:39 -05005772 struct lpfc_hba *phba = vport->phba;
5773 char name[64];
5774 uint32_t num, i;
James Smartf6c3bdf2013-12-17 20:29:59 -05005775 bool pport_setup = false;
James Smart858c9f62007-06-17 19:56:39 -05005776
5777 if (!lpfc_debugfs_enable)
5778 return;
5779
James Smarta58cbd52007-08-02 11:09:43 -04005780 /* Setup lpfc root directory */
5781 if (!lpfc_debugfs_root) {
5782 lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL);
5783 atomic_set(&lpfc_debugfs_hba_count, 0);
James Smarta58cbd52007-08-02 11:09:43 -04005784 }
James Smarta58cbd52007-08-02 11:09:43 -04005785 if (!lpfc_debugfs_start_time)
5786 lpfc_debugfs_start_time = jiffies;
5787
James Smart2a622bf2011-02-16 12:40:06 -05005788 /* Setup funcX directory for specific HBA PCI function */
5789 snprintf(name, sizeof(name), "fn%d", phba->brd_no);
James Smarta58cbd52007-08-02 11:09:43 -04005790 if (!phba->hba_debugfs_root) {
James Smartf6c3bdf2013-12-17 20:29:59 -05005791 pport_setup = true;
James Smarta58cbd52007-08-02 11:09:43 -04005792 phba->hba_debugfs_root =
5793 debugfs_create_dir(name, lpfc_debugfs_root);
James Smarta58cbd52007-08-02 11:09:43 -04005794 atomic_inc(&lpfc_debugfs_hba_count);
5795 atomic_set(&phba->debugfs_vport_count, 0);
5796
James Smartc4908502019-01-28 11:14:28 -08005797 /* Multi-XRI pools */
5798 snprintf(name, sizeof(name), "multixripools");
5799 phba->debug_multixri_pools =
5800 debugfs_create_file(name, S_IFREG | 0644,
5801 phba->hba_debugfs_root,
5802 phba,
5803 &lpfc_debugfs_op_multixripools);
5804 if (!phba->debug_multixri_pools) {
5805 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
5806 "0527 Cannot create debugfs multixripools\n");
5807 goto debug_failed;
5808 }
5809
James Smart95bfc6d2019-10-18 14:18:27 -07005810 /* RAS log */
5811 snprintf(name, sizeof(name), "ras_log");
5812 phba->debug_ras_log =
5813 debugfs_create_file(name, 0644,
5814 phba->hba_debugfs_root,
5815 phba, &lpfc_debugfs_ras_log);
5816 if (!phba->debug_ras_log) {
5817 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
5818 "6148 Cannot create debugfs"
5819 " ras_log\n");
5820 goto debug_failed;
5821 }
5822
James Smart78b2d852007-08-02 11:10:21 -04005823 /* Setup hbqinfo */
5824 snprintf(name, sizeof(name), "hbqinfo");
5825 phba->debug_hbqinfo =
James Smart63df6d62019-01-28 11:14:24 -08005826 debugfs_create_file(name, S_IFREG | 0644,
5827 phba->hba_debugfs_root,
5828 phba, &lpfc_debugfs_op_hbqinfo);
James Smart78b2d852007-08-02 11:10:21 -04005829
James Smart6a828b02019-01-28 11:14:31 -08005830#ifdef LPFC_HDWQ_LOCK_STAT
5831 /* Setup lockstat */
5832 snprintf(name, sizeof(name), "lockstat");
5833 phba->debug_lockstat =
James Smart5e5b5112019-01-28 11:14:22 -08005834 debugfs_create_file(name, S_IFREG | 0644,
5835 phba->hba_debugfs_root,
James Smart6a828b02019-01-28 11:14:31 -08005836 phba, &lpfc_debugfs_op_lockstat);
5837 if (!phba->debug_lockstat) {
James Smart5e5b5112019-01-28 11:14:22 -08005838 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
James Smartc835c082019-03-12 16:30:30 -07005839 "4610 Cant create debugfs lockstat\n");
James Smart5e5b5112019-01-28 11:14:22 -08005840 goto debug_failed;
5841 }
James Smart6a828b02019-01-28 11:14:31 -08005842#endif
James Smart5e5b5112019-01-28 11:14:22 -08005843
James Smartc95d6c62008-01-11 01:53:23 -05005844 /* Setup dumpHBASlim */
James Smart2a622bf2011-02-16 12:40:06 -05005845 if (phba->sli_rev < LPFC_SLI_REV4) {
5846 snprintf(name, sizeof(name), "dumpHBASlim");
5847 phba->debug_dumpHBASlim =
5848 debugfs_create_file(name,
5849 S_IFREG|S_IRUGO|S_IWUSR,
5850 phba->hba_debugfs_root,
5851 phba, &lpfc_debugfs_op_dumpHBASlim);
James Smart2a622bf2011-02-16 12:40:06 -05005852 } else
5853 phba->debug_dumpHBASlim = NULL;
James Smartc95d6c62008-01-11 01:53:23 -05005854
5855 /* Setup dumpHostSlim */
James Smart2a622bf2011-02-16 12:40:06 -05005856 if (phba->sli_rev < LPFC_SLI_REV4) {
5857 snprintf(name, sizeof(name), "dumpHostSlim");
5858 phba->debug_dumpHostSlim =
5859 debugfs_create_file(name,
5860 S_IFREG|S_IRUGO|S_IWUSR,
5861 phba->hba_debugfs_root,
5862 phba, &lpfc_debugfs_op_dumpHostSlim);
James Smart2a622bf2011-02-16 12:40:06 -05005863 } else
Felipe Penab28d1082013-10-18 20:15:37 -03005864 phba->debug_dumpHostSlim = NULL;
James Smarta58cbd52007-08-02 11:09:43 -04005865
James Smartf9bb2da2011-10-10 21:34:11 -04005866 /* Setup DIF Error Injections */
5867 snprintf(name, sizeof(name), "InjErrLBA");
5868 phba->debug_InjErrLBA =
5869 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5870 phba->hba_debugfs_root,
5871 phba, &lpfc_debugfs_op_dif_err);
James Smartf9bb2da2011-10-10 21:34:11 -04005872 phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
5873
James Smart4ac9b222012-03-01 22:38:29 -05005874 snprintf(name, sizeof(name), "InjErrNPortID");
5875 phba->debug_InjErrNPortID =
5876 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5877 phba->hba_debugfs_root,
5878 phba, &lpfc_debugfs_op_dif_err);
James Smart4ac9b222012-03-01 22:38:29 -05005879
5880 snprintf(name, sizeof(name), "InjErrWWPN");
5881 phba->debug_InjErrWWPN =
5882 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5883 phba->hba_debugfs_root,
5884 phba, &lpfc_debugfs_op_dif_err);
James Smart4ac9b222012-03-01 22:38:29 -05005885
James Smartf9bb2da2011-10-10 21:34:11 -04005886 snprintf(name, sizeof(name), "writeGuardInjErr");
5887 phba->debug_writeGuard =
5888 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5889 phba->hba_debugfs_root,
5890 phba, &lpfc_debugfs_op_dif_err);
James Smartf9bb2da2011-10-10 21:34:11 -04005891
5892 snprintf(name, sizeof(name), "writeAppInjErr");
5893 phba->debug_writeApp =
5894 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5895 phba->hba_debugfs_root,
5896 phba, &lpfc_debugfs_op_dif_err);
James Smartf9bb2da2011-10-10 21:34:11 -04005897
5898 snprintf(name, sizeof(name), "writeRefInjErr");
5899 phba->debug_writeRef =
5900 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5901 phba->hba_debugfs_root,
5902 phba, &lpfc_debugfs_op_dif_err);
James Smartf9bb2da2011-10-10 21:34:11 -04005903
James Smartacd68592012-01-18 16:25:09 -05005904 snprintf(name, sizeof(name), "readGuardInjErr");
5905 phba->debug_readGuard =
5906 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5907 phba->hba_debugfs_root,
5908 phba, &lpfc_debugfs_op_dif_err);
James Smartacd68592012-01-18 16:25:09 -05005909
James Smartf9bb2da2011-10-10 21:34:11 -04005910 snprintf(name, sizeof(name), "readAppInjErr");
5911 phba->debug_readApp =
5912 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5913 phba->hba_debugfs_root,
5914 phba, &lpfc_debugfs_op_dif_err);
James Smartf9bb2da2011-10-10 21:34:11 -04005915
5916 snprintf(name, sizeof(name), "readRefInjErr");
5917 phba->debug_readRef =
5918 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5919 phba->hba_debugfs_root,
5920 phba, &lpfc_debugfs_op_dif_err);
James Smartf9bb2da2011-10-10 21:34:11 -04005921
James Smarta58cbd52007-08-02 11:09:43 -04005922 /* Setup slow ring trace */
5923 if (lpfc_debugfs_max_slow_ring_trc) {
5924 num = lpfc_debugfs_max_slow_ring_trc - 1;
5925 if (num & lpfc_debugfs_max_slow_ring_trc) {
5926 /* Change to be a power of 2 */
5927 num = lpfc_debugfs_max_slow_ring_trc;
5928 i = 0;
5929 while (num > 1) {
5930 num = num >> 1;
5931 i++;
5932 }
5933 lpfc_debugfs_max_slow_ring_trc = (1 << i);
James Smart2ea259e2017-02-12 13:52:27 -08005934 pr_err("lpfc_debugfs_max_disc_trc changed to "
James Smarte8b62012007-08-02 11:10:09 -04005935 "%d\n", lpfc_debugfs_max_disc_trc);
James Smarta58cbd52007-08-02 11:09:43 -04005936 }
5937 }
5938
James Smarta58cbd52007-08-02 11:09:43 -04005939 snprintf(name, sizeof(name), "slow_ring_trace");
5940 phba->debug_slow_ring_trc =
5941 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
5942 phba->hba_debugfs_root,
5943 phba, &lpfc_debugfs_op_slow_ring_trc);
James Smarta58cbd52007-08-02 11:09:43 -04005944 if (!phba->slow_ring_trc) {
5945 phba->slow_ring_trc = kmalloc(
5946 (sizeof(struct lpfc_debugfs_trc) *
5947 lpfc_debugfs_max_slow_ring_trc),
5948 GFP_KERNEL);
5949 if (!phba->slow_ring_trc) {
James Smarte8b62012007-08-02 11:10:09 -04005950 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
James Smartd7c255b2008-08-24 21:50:00 -04005951 "0416 Cannot create debugfs "
James Smarte8b62012007-08-02 11:10:09 -04005952 "slow_ring buffer\n");
James Smarta58cbd52007-08-02 11:09:43 -04005953 goto debug_failed;
5954 }
5955 atomic_set(&phba->slow_ring_trc_cnt, 0);
5956 memset(phba->slow_ring_trc, 0,
5957 (sizeof(struct lpfc_debugfs_trc) *
5958 lpfc_debugfs_max_slow_ring_trc));
5959 }
James Smart2ea259e2017-02-12 13:52:27 -08005960
James Smartbd2cdd52017-02-12 13:52:33 -08005961 snprintf(name, sizeof(name), "nvmeio_trc");
5962 phba->debug_nvmeio_trc =
5963 debugfs_create_file(name, 0644,
5964 phba->hba_debugfs_root,
5965 phba, &lpfc_debugfs_op_nvmeio_trc);
James Smartbd2cdd52017-02-12 13:52:33 -08005966
5967 atomic_set(&phba->nvmeio_trc_cnt, 0);
5968 if (lpfc_debugfs_max_nvmeio_trc) {
5969 num = lpfc_debugfs_max_nvmeio_trc - 1;
5970 if (num & lpfc_debugfs_max_disc_trc) {
5971 /* Change to be a power of 2 */
5972 num = lpfc_debugfs_max_nvmeio_trc;
5973 i = 0;
5974 while (num > 1) {
5975 num = num >> 1;
5976 i++;
5977 }
5978 lpfc_debugfs_max_nvmeio_trc = (1 << i);
5979 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
5980 "0575 lpfc_debugfs_max_nvmeio_trc "
5981 "changed to %d\n",
5982 lpfc_debugfs_max_nvmeio_trc);
5983 }
5984 phba->nvmeio_trc_size = lpfc_debugfs_max_nvmeio_trc;
5985
5986 /* Allocate trace buffer and initialize */
Vasyl Gomonovych1c356ec2017-10-11 21:42:41 +02005987 phba->nvmeio_trc = kzalloc(
James Smartbd2cdd52017-02-12 13:52:33 -08005988 (sizeof(struct lpfc_debugfs_nvmeio_trc) *
5989 phba->nvmeio_trc_size), GFP_KERNEL);
5990
5991 if (!phba->nvmeio_trc) {
5992 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
5993 "0576 Cannot create debugfs "
5994 "nvmeio_trc buffer\n");
5995 goto nvmeio_off;
5996 }
James Smartbd2cdd52017-02-12 13:52:33 -08005997 phba->nvmeio_trc_on = 1;
5998 phba->nvmeio_trc_output_idx = 0;
5999 phba->nvmeio_trc = NULL;
6000 } else {
6001nvmeio_off:
6002 phba->nvmeio_trc_size = 0;
6003 phba->nvmeio_trc_on = 0;
6004 phba->nvmeio_trc_output_idx = 0;
6005 phba->nvmeio_trc = NULL;
6006 }
James Smarta58cbd52007-08-02 11:09:43 -04006007 }
6008
6009 snprintf(name, sizeof(name), "vport%d", vport->vpi);
6010 if (!vport->vport_debugfs_root) {
6011 vport->vport_debugfs_root =
6012 debugfs_create_dir(name, phba->hba_debugfs_root);
James Smarta58cbd52007-08-02 11:09:43 -04006013 atomic_inc(&phba->debugfs_vport_count);
6014 }
6015
James Smart858c9f62007-06-17 19:56:39 -05006016 if (lpfc_debugfs_max_disc_trc) {
6017 num = lpfc_debugfs_max_disc_trc - 1;
6018 if (num & lpfc_debugfs_max_disc_trc) {
6019 /* Change to be a power of 2 */
6020 num = lpfc_debugfs_max_disc_trc;
6021 i = 0;
6022 while (num > 1) {
6023 num = num >> 1;
6024 i++;
6025 }
6026 lpfc_debugfs_max_disc_trc = (1 << i);
James Smart2ea259e2017-02-12 13:52:27 -08006027 pr_err("lpfc_debugfs_max_disc_trc changed to %d\n",
James Smarte8b62012007-08-02 11:10:09 -04006028 lpfc_debugfs_max_disc_trc);
James Smart858c9f62007-06-17 19:56:39 -05006029 }
6030 }
6031
Adrian Bunkff86ba52007-10-18 12:52:37 +02006032 vport->disc_trc = kzalloc(
James Smarta58cbd52007-08-02 11:09:43 -04006033 (sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc),
James Smart858c9f62007-06-17 19:56:39 -05006034 GFP_KERNEL);
6035
James Smarta58cbd52007-08-02 11:09:43 -04006036 if (!vport->disc_trc) {
James Smarte8b62012007-08-02 11:10:09 -04006037 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
James Smartd7c255b2008-08-24 21:50:00 -04006038 "0418 Cannot create debugfs disc trace "
James Smarte8b62012007-08-02 11:10:09 -04006039 "buffer\n");
James Smart858c9f62007-06-17 19:56:39 -05006040 goto debug_failed;
James Smarta58cbd52007-08-02 11:09:43 -04006041 }
6042 atomic_set(&vport->disc_trc_cnt, 0);
James Smart858c9f62007-06-17 19:56:39 -05006043
6044 snprintf(name, sizeof(name), "discovery_trace");
6045 vport->debug_disc_trc =
6046 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6047 vport->vport_debugfs_root,
6048 vport, &lpfc_debugfs_op_disc_trc);
James Smart858c9f62007-06-17 19:56:39 -05006049 snprintf(name, sizeof(name), "nodelist");
6050 vport->debug_nodelist =
6051 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6052 vport->vport_debugfs_root,
6053 vport, &lpfc_debugfs_op_nodelist);
James Smart2a622bf2011-02-16 12:40:06 -05006054
James Smartbd2cdd52017-02-12 13:52:33 -08006055 snprintf(name, sizeof(name), "nvmestat");
6056 vport->debug_nvmestat =
6057 debugfs_create_file(name, 0644,
6058 vport->vport_debugfs_root,
6059 vport, &lpfc_debugfs_op_nvmestat);
James Smartbd2cdd52017-02-12 13:52:33 -08006060
James Smart4c47efc2019-01-28 11:14:25 -08006061 snprintf(name, sizeof(name), "scsistat");
6062 vport->debug_scsistat =
6063 debugfs_create_file(name, 0644,
6064 vport->vport_debugfs_root,
6065 vport, &lpfc_debugfs_op_scsistat);
6066 if (!vport->debug_scsistat) {
6067 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
James Smartc835c082019-03-12 16:30:30 -07006068 "4611 Cannot create debugfs scsistat\n");
James Smart4c47efc2019-01-28 11:14:25 -08006069 goto debug_failed;
6070 }
6071
James Smartbd2cdd52017-02-12 13:52:33 -08006072 snprintf(name, sizeof(name), "nvmektime");
6073 vport->debug_nvmektime =
6074 debugfs_create_file(name, 0644,
6075 vport->vport_debugfs_root,
6076 vport, &lpfc_debugfs_op_nvmektime);
James Smartbd2cdd52017-02-12 13:52:33 -08006077
6078 snprintf(name, sizeof(name), "cpucheck");
6079 vport->debug_cpucheck =
6080 debugfs_create_file(name, 0644,
6081 vport->vport_debugfs_root,
6082 vport, &lpfc_debugfs_op_cpucheck);
James Smartbd2cdd52017-02-12 13:52:33 -08006083
James Smart2a622bf2011-02-16 12:40:06 -05006084 /*
James Smartf6c3bdf2013-12-17 20:29:59 -05006085 * The following section is for additional directories/files for the
6086 * physical port.
6087 */
6088
6089 if (!pport_setup)
6090 goto debug_failed;
6091
6092 /*
James Smart2a622bf2011-02-16 12:40:06 -05006093 * iDiag debugfs root entry points for SLI4 device only
6094 */
6095 if (phba->sli_rev < LPFC_SLI_REV4)
6096 goto debug_failed;
6097
6098 snprintf(name, sizeof(name), "iDiag");
6099 if (!phba->idiag_root) {
6100 phba->idiag_root =
6101 debugfs_create_dir(name, phba->hba_debugfs_root);
James Smart2a622bf2011-02-16 12:40:06 -05006102 /* Initialize iDiag data structure */
6103 memset(&idiag, 0, sizeof(idiag));
6104 }
6105
6106 /* iDiag read PCI config space */
6107 snprintf(name, sizeof(name), "pciCfg");
6108 if (!phba->idiag_pci_cfg) {
6109 phba->idiag_pci_cfg =
6110 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6111 phba->idiag_root, phba, &lpfc_idiag_op_pciCfg);
James Smart2a622bf2011-02-16 12:40:06 -05006112 idiag.offset.last_rd = 0;
6113 }
6114
James Smartb76f2dc2011-07-22 18:37:42 -04006115 /* iDiag PCI BAR access */
6116 snprintf(name, sizeof(name), "barAcc");
6117 if (!phba->idiag_bar_acc) {
6118 phba->idiag_bar_acc =
6119 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6120 phba->idiag_root, phba, &lpfc_idiag_op_barAcc);
James Smartb76f2dc2011-07-22 18:37:42 -04006121 idiag.offset.last_rd = 0;
6122 }
6123
James Smart2a622bf2011-02-16 12:40:06 -05006124 /* iDiag get PCI function queue information */
6125 snprintf(name, sizeof(name), "queInfo");
6126 if (!phba->idiag_que_info) {
6127 phba->idiag_que_info =
6128 debugfs_create_file(name, S_IFREG|S_IRUGO,
6129 phba->idiag_root, phba, &lpfc_idiag_op_queInfo);
James Smart2a622bf2011-02-16 12:40:06 -05006130 }
6131
James Smart86a80842011-04-16 11:03:04 -04006132 /* iDiag access PCI function queue */
6133 snprintf(name, sizeof(name), "queAcc");
6134 if (!phba->idiag_que_acc) {
6135 phba->idiag_que_acc =
6136 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6137 phba->idiag_root, phba, &lpfc_idiag_op_queAcc);
James Smart86a80842011-04-16 11:03:04 -04006138 }
6139
6140 /* iDiag access PCI function doorbell registers */
6141 snprintf(name, sizeof(name), "drbAcc");
6142 if (!phba->idiag_drb_acc) {
6143 phba->idiag_drb_acc =
6144 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6145 phba->idiag_root, phba, &lpfc_idiag_op_drbAcc);
James Smart86a80842011-04-16 11:03:04 -04006146 }
6147
James Smartb76f2dc2011-07-22 18:37:42 -04006148 /* iDiag access PCI function control registers */
6149 snprintf(name, sizeof(name), "ctlAcc");
6150 if (!phba->idiag_ctl_acc) {
6151 phba->idiag_ctl_acc =
6152 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6153 phba->idiag_root, phba, &lpfc_idiag_op_ctlAcc);
James Smartb76f2dc2011-07-22 18:37:42 -04006154 }
6155
6156 /* iDiag access mbox commands */
6157 snprintf(name, sizeof(name), "mbxAcc");
6158 if (!phba->idiag_mbx_acc) {
6159 phba->idiag_mbx_acc =
6160 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
6161 phba->idiag_root, phba, &lpfc_idiag_op_mbxAcc);
James Smartb76f2dc2011-07-22 18:37:42 -04006162 }
6163
6164 /* iDiag extents access commands */
6165 if (phba->sli4_hba.extents_in_use) {
6166 snprintf(name, sizeof(name), "extAcc");
6167 if (!phba->idiag_ext_acc) {
6168 phba->idiag_ext_acc =
6169 debugfs_create_file(name,
6170 S_IFREG|S_IRUGO|S_IWUSR,
6171 phba->idiag_root, phba,
6172 &lpfc_idiag_op_extAcc);
James Smartb76f2dc2011-07-22 18:37:42 -04006173 }
6174 }
6175
James Smart858c9f62007-06-17 19:56:39 -05006176debug_failed:
6177 return;
6178#endif
6179}
6180
James Smarte59058c2008-08-24 21:49:00 -04006181/**
James Smart3621a712009-04-06 18:47:14 -04006182 * lpfc_debugfs_terminate - Tear down debugfs infrastructure for this vport
James Smarte59058c2008-08-24 21:49:00 -04006183 * @vport: The vport pointer to remove from debugfs.
6184 *
6185 * Description:
6186 * When Debugfs is configured this routine removes debugfs file system elements
6187 * that are specific to this vport. It also checks to see if there are any
6188 * users left for the debugfs directories associated with the HBA and driver. If
6189 * this is the last user of the HBA directory or driver directory then it will
6190 * remove those from the debugfs infrastructure as well.
6191 **/
James Smart858c9f62007-06-17 19:56:39 -05006192inline void
6193lpfc_debugfs_terminate(struct lpfc_vport *vport)
6194{
James Smart923e4b62008-12-04 22:40:07 -05006195#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
James Smart858c9f62007-06-17 19:56:39 -05006196 struct lpfc_hba *phba = vport->phba;
6197
James Smarteafe89f2017-04-21 16:04:52 -07006198 kfree(vport->disc_trc);
6199 vport->disc_trc = NULL;
James Smartbd2cdd52017-02-12 13:52:33 -08006200
6201 debugfs_remove(vport->debug_disc_trc); /* discovery_trace */
6202 vport->debug_disc_trc = NULL;
6203
6204 debugfs_remove(vport->debug_nodelist); /* nodelist */
6205 vport->debug_nodelist = NULL;
6206
6207 debugfs_remove(vport->debug_nvmestat); /* nvmestat */
6208 vport->debug_nvmestat = NULL;
6209
James Smart4c47efc2019-01-28 11:14:25 -08006210 debugfs_remove(vport->debug_scsistat); /* scsistat */
6211 vport->debug_scsistat = NULL;
6212
James Smartbd2cdd52017-02-12 13:52:33 -08006213 debugfs_remove(vport->debug_nvmektime); /* nvmektime */
6214 vport->debug_nvmektime = NULL;
6215
6216 debugfs_remove(vport->debug_cpucheck); /* cpucheck */
6217 vport->debug_cpucheck = NULL;
6218
James Smart858c9f62007-06-17 19:56:39 -05006219 if (vport->vport_debugfs_root) {
6220 debugfs_remove(vport->vport_debugfs_root); /* vportX */
6221 vport->vport_debugfs_root = NULL;
6222 atomic_dec(&phba->debugfs_vport_count);
6223 }
James Smartbd2cdd52017-02-12 13:52:33 -08006224
James Smart858c9f62007-06-17 19:56:39 -05006225 if (atomic_read(&phba->debugfs_vport_count) == 0) {
James Smarta58cbd52007-08-02 11:09:43 -04006226
James Smartc4908502019-01-28 11:14:28 -08006227 debugfs_remove(phba->debug_multixri_pools); /* multixripools*/
6228 phba->debug_multixri_pools = NULL;
6229
James Smartbd2cdd52017-02-12 13:52:33 -08006230 debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */
6231 phba->debug_hbqinfo = NULL;
James Smarte2a0a9d2008-12-04 22:40:02 -05006232
James Smart95bfc6d2019-10-18 14:18:27 -07006233 debugfs_remove(phba->debug_ras_log);
6234 phba->debug_ras_log = NULL;
6235
James Smart6a828b02019-01-28 11:14:31 -08006236#ifdef LPFC_HDWQ_LOCK_STAT
6237 debugfs_remove(phba->debug_lockstat); /* lockstat */
6238 phba->debug_lockstat = NULL;
6239#endif
James Smartbd2cdd52017-02-12 13:52:33 -08006240 debugfs_remove(phba->debug_dumpHBASlim); /* HBASlim */
6241 phba->debug_dumpHBASlim = NULL;
6242
6243 debugfs_remove(phba->debug_dumpHostSlim); /* HostSlim */
6244 phba->debug_dumpHostSlim = NULL;
6245
James Smartbd2cdd52017-02-12 13:52:33 -08006246 debugfs_remove(phba->debug_InjErrLBA); /* InjErrLBA */
6247 phba->debug_InjErrLBA = NULL;
6248
6249 debugfs_remove(phba->debug_InjErrNPortID);
6250 phba->debug_InjErrNPortID = NULL;
6251
6252 debugfs_remove(phba->debug_InjErrWWPN); /* InjErrWWPN */
6253 phba->debug_InjErrWWPN = NULL;
6254
6255 debugfs_remove(phba->debug_writeGuard); /* writeGuard */
6256 phba->debug_writeGuard = NULL;
6257
6258 debugfs_remove(phba->debug_writeApp); /* writeApp */
6259 phba->debug_writeApp = NULL;
6260
6261 debugfs_remove(phba->debug_writeRef); /* writeRef */
6262 phba->debug_writeRef = NULL;
6263
6264 debugfs_remove(phba->debug_readGuard); /* readGuard */
6265 phba->debug_readGuard = NULL;
6266
6267 debugfs_remove(phba->debug_readApp); /* readApp */
6268 phba->debug_readApp = NULL;
6269
6270 debugfs_remove(phba->debug_readRef); /* readRef */
6271 phba->debug_readRef = NULL;
James Smarte2a0a9d2008-12-04 22:40:02 -05006272
James Smarteafe89f2017-04-21 16:04:52 -07006273 kfree(phba->slow_ring_trc);
6274 phba->slow_ring_trc = NULL;
James Smartbd2cdd52017-02-12 13:52:33 -08006275
6276 /* slow_ring_trace */
6277 debugfs_remove(phba->debug_slow_ring_trc);
6278 phba->debug_slow_ring_trc = NULL;
6279
6280 debugfs_remove(phba->debug_nvmeio_trc);
6281 phba->debug_nvmeio_trc = NULL;
6282
6283 kfree(phba->nvmeio_trc);
6284 phba->nvmeio_trc = NULL;
James Smarta58cbd52007-08-02 11:09:43 -04006285
James Smart2a622bf2011-02-16 12:40:06 -05006286 /*
6287 * iDiag release
6288 */
6289 if (phba->sli_rev == LPFC_SLI_REV4) {
James Smartbd2cdd52017-02-12 13:52:33 -08006290 /* iDiag extAcc */
6291 debugfs_remove(phba->idiag_ext_acc);
6292 phba->idiag_ext_acc = NULL;
6293
6294 /* iDiag mbxAcc */
6295 debugfs_remove(phba->idiag_mbx_acc);
6296 phba->idiag_mbx_acc = NULL;
6297
6298 /* iDiag ctlAcc */
6299 debugfs_remove(phba->idiag_ctl_acc);
6300 phba->idiag_ctl_acc = NULL;
6301
6302 /* iDiag drbAcc */
6303 debugfs_remove(phba->idiag_drb_acc);
6304 phba->idiag_drb_acc = NULL;
6305
6306 /* iDiag queAcc */
6307 debugfs_remove(phba->idiag_que_acc);
6308 phba->idiag_que_acc = NULL;
6309
6310 /* iDiag queInfo */
6311 debugfs_remove(phba->idiag_que_info);
6312 phba->idiag_que_info = NULL;
6313
6314 /* iDiag barAcc */
6315 debugfs_remove(phba->idiag_bar_acc);
6316 phba->idiag_bar_acc = NULL;
6317
6318 /* iDiag pciCfg */
6319 debugfs_remove(phba->idiag_pci_cfg);
6320 phba->idiag_pci_cfg = NULL;
James Smart2a622bf2011-02-16 12:40:06 -05006321
6322 /* Finally remove the iDiag debugfs root */
James Smartbd2cdd52017-02-12 13:52:33 -08006323 debugfs_remove(phba->idiag_root);
6324 phba->idiag_root = NULL;
James Smart2a622bf2011-02-16 12:40:06 -05006325 }
6326
James Smarta58cbd52007-08-02 11:09:43 -04006327 if (phba->hba_debugfs_root) {
James Smart2a622bf2011-02-16 12:40:06 -05006328 debugfs_remove(phba->hba_debugfs_root); /* fnX */
James Smarta58cbd52007-08-02 11:09:43 -04006329 phba->hba_debugfs_root = NULL;
6330 atomic_dec(&lpfc_debugfs_hba_count);
6331 }
6332
James Smart667a7662017-05-15 15:20:48 -07006333 if (atomic_read(&lpfc_debugfs_hba_count) == 0) {
6334 debugfs_remove(lpfc_debugfs_root); /* lpfc */
6335 lpfc_debugfs_root = NULL;
6336 }
James Smart858c9f62007-06-17 19:56:39 -05006337 }
6338#endif
James Smarta58cbd52007-08-02 11:09:43 -04006339 return;
James Smart858c9f62007-06-17 19:56:39 -05006340}
James Smart809c7532012-05-09 21:19:25 -04006341
6342/*
6343 * Driver debug utility routines outside of debugfs. The debug utility
6344 * routines implemented here is intended to be used in the instrumented
6345 * debug driver for debugging host or port issues.
6346 */
6347
6348/**
6349 * lpfc_debug_dump_all_queues - dump all the queues with a hba
6350 * @phba: Pointer to HBA context object.
6351 *
6352 * This function dumps entries of all the queues asociated with the @phba.
6353 **/
6354void
6355lpfc_debug_dump_all_queues(struct lpfc_hba *phba)
6356{
James Smart1d9d5a92017-02-12 13:52:29 -08006357 int idx;
James Smart809c7532012-05-09 21:19:25 -04006358
6359 /*
6360 * Dump Work Queues (WQs)
6361 */
James Smart1d9d5a92017-02-12 13:52:29 -08006362 lpfc_debug_dump_wq(phba, DUMP_MBX, 0);
6363 lpfc_debug_dump_wq(phba, DUMP_ELS, 0);
James Smart895427b2017-02-12 13:52:30 -08006364 lpfc_debug_dump_wq(phba, DUMP_NVMELS, 0);
James Smart809c7532012-05-09 21:19:25 -04006365
James Smartcdb42be2019-01-28 11:14:21 -08006366 for (idx = 0; idx < phba->cfg_hdw_queue; idx++)
James Smartc00f62e2019-08-14 16:57:11 -07006367 lpfc_debug_dump_wq(phba, DUMP_IO, idx);
James Smart895427b2017-02-12 13:52:30 -08006368
James Smart809c7532012-05-09 21:19:25 -04006369 lpfc_debug_dump_hdr_rq(phba);
6370 lpfc_debug_dump_dat_rq(phba);
6371 /*
6372 * Dump Complete Queues (CQs)
6373 */
James Smart1d9d5a92017-02-12 13:52:29 -08006374 lpfc_debug_dump_cq(phba, DUMP_MBX, 0);
6375 lpfc_debug_dump_cq(phba, DUMP_ELS, 0);
James Smart895427b2017-02-12 13:52:30 -08006376 lpfc_debug_dump_cq(phba, DUMP_NVMELS, 0);
James Smart809c7532012-05-09 21:19:25 -04006377
James Smartcdb42be2019-01-28 11:14:21 -08006378 for (idx = 0; idx < phba->cfg_hdw_queue; idx++)
James Smartc00f62e2019-08-14 16:57:11 -07006379 lpfc_debug_dump_cq(phba, DUMP_IO, idx);
James Smart895427b2017-02-12 13:52:30 -08006380
James Smart809c7532012-05-09 21:19:25 -04006381 /*
6382 * Dump Event Queues (EQs)
6383 */
James Smartcdb42be2019-01-28 11:14:21 -08006384 for (idx = 0; idx < phba->cfg_hdw_queue; idx++)
James Smart1d9d5a92017-02-12 13:52:29 -08006385 lpfc_debug_dump_hba_eq(phba, idx);
James Smart809c7532012-05-09 21:19:25 -04006386}