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