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