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

source code of linux/drivers/scsi/lpfc/lpfc_debugfs.c