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