]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/scsi/lpfc/lpfc_debugfs.c
[SCSI] lpfc 8.2.2 : Miscellaneous Bug Fixes
[linux-2.6-omap-h63xx.git] / drivers / scsi / lpfc / lpfc_debugfs.c
1 /*******************************************************************
2  * This file is part of the Emulex Linux Device Driver for         *
3  * Fibre Channel Host Bus Adapters.                                *
4  * Copyright (C) 2007 Emulex.  All rights reserved.                *
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>
23 #include <linux/dma-mapping.h>
24 #include <linux/idr.h>
25 #include <linux/interrupt.h>
26 #include <linux/kthread.h>
27 #include <linux/pci.h>
28 #include <linux/spinlock.h>
29 #include <linux/ctype.h>
30 #include <linux/version.h>
31
32 #include <scsi/scsi.h>
33 #include <scsi/scsi_device.h>
34 #include <scsi/scsi_host.h>
35 #include <scsi/scsi_transport_fc.h>
36
37 #include "lpfc_hw.h"
38 #include "lpfc_sli.h"
39 #include "lpfc_disc.h"
40 #include "lpfc_scsi.h"
41 #include "lpfc.h"
42 #include "lpfc_logmsg.h"
43 #include "lpfc_crtn.h"
44 #include "lpfc_vport.h"
45 #include "lpfc_version.h"
46 #include "lpfc_vport.h"
47 #include "lpfc_debugfs.h"
48
49 #ifdef CONFIG_LPFC_DEBUG_FS
50 /* debugfs interface
51  *
52  * To access this interface the user should:
53  * # mkdir /debug
54  * # mount -t debugfs none /debug
55  *
56  * The lpfc debugfs directory hierachy is:
57  * lpfc/lpfcX/vportY
58  * where X is the lpfc hba unique_id
59  * where Y is the vport VPI on that hba
60  *
61  * Debugging services available per vport:
62  * discovery_trace
63  * This is an ACSII readable file that contains a trace of the last
64  * lpfc_debugfs_max_disc_trc events that happened on a specific vport.
65  * See lpfc_debugfs.h for different categories of
66  * discovery events. To enable the discovery trace, the following
67  * module parameters must be set:
68  * lpfc_debugfs_enable=1         Turns on lpfc debugfs filesystem support
69  * lpfc_debugfs_max_disc_trc=X   Where X is the event trace depth for
70  *                               EACH vport. X MUST also be a power of 2.
71  * lpfc_debugfs_mask_disc_trc=Y  Where Y is an event mask as defined in
72  *                               lpfc_debugfs.h .
73  */
74 static int lpfc_debugfs_enable = 1;
75 module_param(lpfc_debugfs_enable, int, 0);
76 MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services");
77
78 /* This MUST be a power of 2 */
79 static int lpfc_debugfs_max_disc_trc = 0;
80 module_param(lpfc_debugfs_max_disc_trc, int, 0);
81 MODULE_PARM_DESC(lpfc_debugfs_max_disc_trc,
82         "Set debugfs discovery trace depth");
83
84 /* This MUST be a power of 2 */
85 static int lpfc_debugfs_max_slow_ring_trc = 0;
86 module_param(lpfc_debugfs_max_slow_ring_trc, int, 0);
87 MODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc,
88         "Set debugfs slow ring trace depth");
89
90 static int lpfc_debugfs_mask_disc_trc = 0;
91 module_param(lpfc_debugfs_mask_disc_trc, int, 0);
92 MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc,
93         "Set debugfs discovery trace mask");
94
95 #include <linux/debugfs.h>
96
97 /* size of output line, for discovery_trace and slow_ring_trace */
98 #define LPFC_DEBUG_TRC_ENTRY_SIZE 100
99
100 /* nodelist output buffer size */
101 #define LPFC_NODELIST_SIZE 8192
102 #define LPFC_NODELIST_ENTRY_SIZE 120
103
104 /* dumpslim output buffer size */
105 #define LPFC_DUMPSLIM_SIZE 4096
106
107 /* hbqinfo output buffer size */
108 #define LPFC_HBQINFO_SIZE 8192
109
110 struct lpfc_debug {
111         char *buffer;
112         int  len;
113 };
114
115 extern struct lpfc_hbq_init *lpfc_hbq_defs[];
116
117 atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0);
118 unsigned long lpfc_debugfs_start_time = 0L;
119
120 static int
121 lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
122 {
123         int i, index, len, enable;
124         uint32_t ms;
125         struct lpfc_debugfs_trc *dtp;
126         char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE];
127
128
129         enable = lpfc_debugfs_enable;
130         lpfc_debugfs_enable = 0;
131
132         len = 0;
133         index = (atomic_read(&vport->disc_trc_cnt) + 1) &
134                 (lpfc_debugfs_max_disc_trc - 1);
135         for (i = index; i < lpfc_debugfs_max_disc_trc; i++) {
136                 dtp = vport->disc_trc + i;
137                 if (!dtp->fmt)
138                         continue;
139                 ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
140                 snprintf(buffer,
141                         LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
142                         dtp->seq_cnt, ms, dtp->fmt);
143                 len +=  snprintf(buf+len, size-len, buffer,
144                         dtp->data1, dtp->data2, dtp->data3);
145         }
146         for (i = 0; i < index; i++) {
147                 dtp = vport->disc_trc + i;
148                 if (!dtp->fmt)
149                         continue;
150                 ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
151                 snprintf(buffer,
152                         LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
153                         dtp->seq_cnt, ms, dtp->fmt);
154                 len +=  snprintf(buf+len, size-len, buffer,
155                         dtp->data1, dtp->data2, dtp->data3);
156         }
157
158         lpfc_debugfs_enable = enable;
159         return len;
160 }
161
162 static int
163 lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
164 {
165         int i, index, len, enable;
166         uint32_t ms;
167         struct lpfc_debugfs_trc *dtp;
168         char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE];
169
170
171         enable = lpfc_debugfs_enable;
172         lpfc_debugfs_enable = 0;
173
174         len = 0;
175         index = (atomic_read(&phba->slow_ring_trc_cnt) + 1) &
176                 (lpfc_debugfs_max_slow_ring_trc - 1);
177         for (i = index; i < lpfc_debugfs_max_slow_ring_trc; i++) {
178                 dtp = phba->slow_ring_trc + i;
179                 if (!dtp->fmt)
180                         continue;
181                 ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
182                 snprintf(buffer,
183                         LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
184                         dtp->seq_cnt, ms, dtp->fmt);
185                 len +=  snprintf(buf+len, size-len, buffer,
186                         dtp->data1, dtp->data2, dtp->data3);
187         }
188         for (i = 0; i < index; i++) {
189                 dtp = phba->slow_ring_trc + i;
190                 if (!dtp->fmt)
191                         continue;
192                 ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
193                 snprintf(buffer,
194                         LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n",
195                         dtp->seq_cnt, ms, dtp->fmt);
196                 len +=  snprintf(buf+len, size-len, buffer,
197                         dtp->data1, dtp->data2, dtp->data3);
198         }
199
200         lpfc_debugfs_enable = enable;
201         return len;
202 }
203
204 int lpfc_debugfs_last_hbq = -1;
205
206 static int
207 lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size)
208 {
209         int len = 0;
210         int cnt, i, j, found, posted, low;
211         uint32_t phys, raw_index, getidx;
212         struct lpfc_hbq_init *hip;
213         struct hbq_s *hbqs;
214         struct lpfc_hbq_entry *hbqe;
215         struct lpfc_dmabuf *d_buf;
216         struct hbq_dmabuf *hbq_buf;
217
218         cnt = LPFC_HBQINFO_SIZE;
219         spin_lock_irq(&phba->hbalock);
220
221         /* toggle between multiple hbqs, if any */
222         i = lpfc_sli_hbq_count();
223         if (i > 1) {
224                  lpfc_debugfs_last_hbq++;
225                  if (lpfc_debugfs_last_hbq >= i)
226                         lpfc_debugfs_last_hbq = 0;
227         }
228         else
229                 lpfc_debugfs_last_hbq = 0;
230
231         i = lpfc_debugfs_last_hbq;
232
233         len +=  snprintf(buf+len, size-len, "HBQ %d Info\n", i);
234
235         hbqs =  &phba->hbqs[i];
236         posted = 0;
237         list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list)
238                 posted++;
239
240         hip =  lpfc_hbq_defs[i];
241         len +=  snprintf(buf+len, size-len,
242                 "idx:%d prof:%d rn:%d bufcnt:%d icnt:%d acnt:%d posted %d\n",
243                 hip->hbq_index, hip->profile, hip->rn,
244                 hip->buffer_count, hip->init_count, hip->add_count, posted);
245
246         raw_index = phba->hbq_get[i];
247         getidx = le32_to_cpu(raw_index);
248         len +=  snprintf(buf+len, size-len,
249                 "entrys:%d Put:%d nPut:%d localGet:%d hbaGet:%d\n",
250                 hbqs->entry_count, hbqs->hbqPutIdx, hbqs->next_hbqPutIdx,
251                 hbqs->local_hbqGetIdx, getidx);
252
253         hbqe = (struct lpfc_hbq_entry *) phba->hbqs[i].hbq_virt;
254         for (j=0; j<hbqs->entry_count; j++) {
255                 len +=  snprintf(buf+len, size-len,
256                         "%03d: %08x %04x %05x ", j,
257                         hbqe->bde.addrLow, hbqe->bde.tus.w, hbqe->buffer_tag);
258
259                 i = 0;
260                 found = 0;
261
262                 /* First calculate if slot has an associated posted buffer */
263                 low = hbqs->hbqPutIdx - posted;
264                 if (low >= 0) {
265                         if ((j >= hbqs->hbqPutIdx) || (j < low)) {
266                                 len +=  snprintf(buf+len, size-len, "Unused\n");
267                                 goto skipit;
268                         }
269                 }
270                 else {
271                         if ((j >= hbqs->hbqPutIdx) &&
272                                 (j < (hbqs->entry_count+low))) {
273                                 len +=  snprintf(buf+len, size-len, "Unused\n");
274                                 goto skipit;
275                         }
276                 }
277
278                 /* Get the Buffer info for the posted buffer */
279                 list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list) {
280                         hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf);
281                         phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff);
282                         if (phys == hbqe->bde.addrLow) {
283                                 len +=  snprintf(buf+len, size-len,
284                                         "Buf%d: %p %06x\n", i,
285                                         hbq_buf->dbuf.virt, hbq_buf->tag);
286                                 found = 1;
287                                 break;
288                         }
289                         i++;
290                 }
291                 if (!found) {
292                         len +=  snprintf(buf+len, size-len, "No DMAinfo?\n");
293                 }
294 skipit:
295                 hbqe++;
296                 if (len > LPFC_HBQINFO_SIZE - 54)
297                         break;
298         }
299         spin_unlock_irq(&phba->hbalock);
300         return len;
301 }
302
303 static int
304 lpfc_debugfs_dumpslim_data(struct lpfc_hba *phba, char *buf, int size)
305 {
306         int len = 0;
307         int cnt, i, off;
308         uint32_t word0, word1, word2, word3;
309         uint32_t *ptr;
310         struct lpfc_pgp *pgpp;
311         struct lpfc_sli *psli = &phba->sli;
312         struct lpfc_sli_ring *pring;
313
314         cnt = LPFC_DUMPSLIM_SIZE;
315         off = 0;
316         spin_lock_irq(&phba->hbalock);
317
318         len +=  snprintf(buf+len, size-len, "SLIM Mailbox\n");
319         ptr = (uint32_t *)phba->slim2p;
320         i = sizeof(MAILBOX_t);
321         while (i > 0) {
322                 len +=  snprintf(buf+len, size-len,
323                 "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
324                 off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4),
325                 *(ptr+5), *(ptr+6), *(ptr+7));
326                 ptr += 8;
327                 i -= (8 * sizeof(uint32_t));
328                 off += (8 * sizeof(uint32_t));
329         }
330
331         len +=  snprintf(buf+len, size-len, "SLIM PCB\n");
332         ptr = (uint32_t *)&phba->slim2p->pcb;
333         i = sizeof(PCB_t);
334         while (i > 0) {
335                 len +=  snprintf(buf+len, size-len,
336                 "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
337                 off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4),
338                 *(ptr+5), *(ptr+6), *(ptr+7));
339                 ptr += 8;
340                 i -= (8 * sizeof(uint32_t));
341                 off += (8 * sizeof(uint32_t));
342         }
343
344         pgpp = (struct lpfc_pgp *)&phba->slim2p->mbx.us.s3_pgp.port;
345         pring = &psli->ring[0];
346         len +=  snprintf(buf+len, size-len,
347                 "Ring 0: CMD GetInx:%d (Max:%d Next:%d Local:%d flg:x%x)  "
348                 "RSP PutInx:%d Max:%d\n",
349                 pgpp->cmdGetInx, pring->numCiocb,
350                 pring->next_cmdidx, pring->local_getidx, pring->flag,
351                 pgpp->rspPutInx, pring->numRiocb);
352         pgpp++;
353
354         pring = &psli->ring[1];
355         len +=  snprintf(buf+len, size-len,
356                 "Ring 1: CMD GetInx:%d (Max:%d Next:%d Local:%d flg:x%x)  "
357                 "RSP PutInx:%d Max:%d\n",
358                 pgpp->cmdGetInx, pring->numCiocb,
359                 pring->next_cmdidx, pring->local_getidx, pring->flag,
360                 pgpp->rspPutInx, pring->numRiocb);
361         pgpp++;
362
363         pring = &psli->ring[2];
364         len +=  snprintf(buf+len, size-len,
365                 "Ring 2: CMD GetInx:%d (Max:%d Next:%d Local:%d flg:x%x)  "
366                 "RSP PutInx:%d Max:%d\n",
367                 pgpp->cmdGetInx, pring->numCiocb,
368                 pring->next_cmdidx, pring->local_getidx, pring->flag,
369                 pgpp->rspPutInx, pring->numRiocb);
370         pgpp++;
371
372         pring = &psli->ring[3];
373         len +=  snprintf(buf+len, size-len,
374                 "Ring 3: CMD GetInx:%d (Max:%d Next:%d Local:%d flg:x%x)  "
375                 "RSP PutInx:%d Max:%d\n",
376                 pgpp->cmdGetInx, pring->numCiocb,
377                 pring->next_cmdidx, pring->local_getidx, pring->flag,
378                 pgpp->rspPutInx, pring->numRiocb);
379
380
381         ptr = (uint32_t *)&phba->slim2p->mbx.us.s3_pgp.hbq_get;
382         word0 = readl(phba->HAregaddr);
383         word1 = readl(phba->CAregaddr);
384         word2 = readl(phba->HSregaddr);
385         word3 = readl(phba->HCregaddr);
386         len +=  snprintf(buf+len, size-len, "HA:%08x CA:%08x HS:%08x HC:%08x\n",
387         word0, word1, word2, word3);
388         spin_unlock_irq(&phba->hbalock);
389         return len;
390 }
391
392 static int
393 lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
394 {
395         int len = 0;
396         int cnt;
397         struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
398         struct lpfc_nodelist *ndlp;
399         unsigned char *statep, *name;
400
401         cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
402
403         spin_lock_irq(shost->host_lock);
404         list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
405                 if (!cnt) {
406                         len +=  snprintf(buf+len, size-len,
407                                 "Missing Nodelist Entries\n");
408                         break;
409                 }
410                 cnt--;
411                 switch (ndlp->nlp_state) {
412                 case NLP_STE_UNUSED_NODE:
413                         statep = "UNUSED";
414                         break;
415                 case NLP_STE_PLOGI_ISSUE:
416                         statep = "PLOGI ";
417                         break;
418                 case NLP_STE_ADISC_ISSUE:
419                         statep = "ADISC ";
420                         break;
421                 case NLP_STE_REG_LOGIN_ISSUE:
422                         statep = "REGLOG";
423                         break;
424                 case NLP_STE_PRLI_ISSUE:
425                         statep = "PRLI  ";
426                         break;
427                 case NLP_STE_UNMAPPED_NODE:
428                         statep = "UNMAP ";
429                         break;
430                 case NLP_STE_MAPPED_NODE:
431                         statep = "MAPPED";
432                         break;
433                 case NLP_STE_NPR_NODE:
434                         statep = "NPR   ";
435                         break;
436                 default:
437                         statep = "UNKNOWN";
438                 }
439                 len +=  snprintf(buf+len, size-len, "%s DID:x%06x ",
440                         statep, ndlp->nlp_DID);
441                 name = (unsigned char *)&ndlp->nlp_portname;
442                 len +=  snprintf(buf+len, size-len,
443                         "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",
444                         *name, *(name+1), *(name+2), *(name+3),
445                         *(name+4), *(name+5), *(name+6), *(name+7));
446                 name = (unsigned char *)&ndlp->nlp_nodename;
447                 len +=  snprintf(buf+len, size-len,
448                         "WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",
449                         *name, *(name+1), *(name+2), *(name+3),
450                         *(name+4), *(name+5), *(name+6), *(name+7));
451                 len +=  snprintf(buf+len, size-len, "RPI:%03d flag:x%08x ",
452                         ndlp->nlp_rpi, ndlp->nlp_flag);
453                 if (!ndlp->nlp_type)
454                         len +=  snprintf(buf+len, size-len, "UNKNOWN_TYPE ");
455                 if (ndlp->nlp_type & NLP_FC_NODE)
456                         len +=  snprintf(buf+len, size-len, "FC_NODE ");
457                 if (ndlp->nlp_type & NLP_FABRIC)
458                         len +=  snprintf(buf+len, size-len, "FABRIC ");
459                 if (ndlp->nlp_type & NLP_FCP_TARGET)
460                         len +=  snprintf(buf+len, size-len, "FCP_TGT sid:%d ",
461                                 ndlp->nlp_sid);
462                 if (ndlp->nlp_type & NLP_FCP_INITIATOR)
463                         len +=  snprintf(buf+len, size-len, "FCP_INITIATOR ");
464                 len += snprintf(buf+len, size-len, "refcnt:%x",
465                         atomic_read(&ndlp->kref.refcount));
466                 len +=  snprintf(buf+len, size-len, "\n");
467         }
468         spin_unlock_irq(shost->host_lock);
469         return len;
470 }
471 #endif
472
473
474 inline void
475 lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt,
476         uint32_t data1, uint32_t data2, uint32_t data3)
477 {
478 #ifdef CONFIG_LPFC_DEBUG_FS
479         struct lpfc_debugfs_trc *dtp;
480         int index;
481
482         if (!(lpfc_debugfs_mask_disc_trc & mask))
483                 return;
484
485         if (!lpfc_debugfs_enable || !lpfc_debugfs_max_disc_trc ||
486                 !vport || !vport->disc_trc)
487                 return;
488
489         index = atomic_inc_return(&vport->disc_trc_cnt) &
490                 (lpfc_debugfs_max_disc_trc - 1);
491         dtp = vport->disc_trc + index;
492         dtp->fmt = fmt;
493         dtp->data1 = data1;
494         dtp->data2 = data2;
495         dtp->data3 = data3;
496         dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt);
497         dtp->jif = jiffies;
498 #endif
499         return;
500 }
501
502 inline void
503 lpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt,
504         uint32_t data1, uint32_t data2, uint32_t data3)
505 {
506 #ifdef CONFIG_LPFC_DEBUG_FS
507         struct lpfc_debugfs_trc *dtp;
508         int index;
509
510         if (!lpfc_debugfs_enable || !lpfc_debugfs_max_slow_ring_trc ||
511                 !phba || !phba->slow_ring_trc)
512                 return;
513
514         index = atomic_inc_return(&phba->slow_ring_trc_cnt) &
515                 (lpfc_debugfs_max_slow_ring_trc - 1);
516         dtp = phba->slow_ring_trc + index;
517         dtp->fmt = fmt;
518         dtp->data1 = data1;
519         dtp->data2 = data2;
520         dtp->data3 = data3;
521         dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt);
522         dtp->jif = jiffies;
523 #endif
524         return;
525 }
526
527 #ifdef CONFIG_LPFC_DEBUG_FS
528 static int
529 lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file)
530 {
531         struct lpfc_vport *vport = inode->i_private;
532         struct lpfc_debug *debug;
533         int size;
534         int rc = -ENOMEM;
535
536         if (!lpfc_debugfs_max_disc_trc) {
537                  rc = -ENOSPC;
538                 goto out;
539         }
540
541         debug = kmalloc(sizeof(*debug), GFP_KERNEL);
542         if (!debug)
543                 goto out;
544
545         /* Round to page boundry */
546         size =  (lpfc_debugfs_max_disc_trc * LPFC_DEBUG_TRC_ENTRY_SIZE);
547         size = PAGE_ALIGN(size);
548
549         debug->buffer = kmalloc(size, GFP_KERNEL);
550         if (!debug->buffer) {
551                 kfree(debug);
552                 goto out;
553         }
554
555         debug->len = lpfc_debugfs_disc_trc_data(vport, debug->buffer, size);
556         file->private_data = debug;
557
558         rc = 0;
559 out:
560         return rc;
561 }
562
563 static int
564 lpfc_debugfs_slow_ring_trc_open(struct inode *inode, struct file *file)
565 {
566         struct lpfc_hba *phba = inode->i_private;
567         struct lpfc_debug *debug;
568         int size;
569         int rc = -ENOMEM;
570
571         if (!lpfc_debugfs_max_slow_ring_trc) {
572                  rc = -ENOSPC;
573                 goto out;
574         }
575
576         debug = kmalloc(sizeof(*debug), GFP_KERNEL);
577         if (!debug)
578                 goto out;
579
580         /* Round to page boundry */
581         size =  (lpfc_debugfs_max_slow_ring_trc * LPFC_DEBUG_TRC_ENTRY_SIZE);
582         size = PAGE_ALIGN(size);
583
584         debug->buffer = kmalloc(size, GFP_KERNEL);
585         if (!debug->buffer) {
586                 kfree(debug);
587                 goto out;
588         }
589
590         debug->len = lpfc_debugfs_slow_ring_trc_data(phba, debug->buffer, size);
591         file->private_data = debug;
592
593         rc = 0;
594 out:
595         return rc;
596 }
597
598 static int
599 lpfc_debugfs_hbqinfo_open(struct inode *inode, struct file *file)
600 {
601         struct lpfc_hba *phba = inode->i_private;
602         struct lpfc_debug *debug;
603         int rc = -ENOMEM;
604
605         debug = kmalloc(sizeof(*debug), GFP_KERNEL);
606         if (!debug)
607                 goto out;
608
609         /* Round to page boundry */
610         debug->buffer = kmalloc(LPFC_HBQINFO_SIZE, GFP_KERNEL);
611         if (!debug->buffer) {
612                 kfree(debug);
613                 goto out;
614         }
615
616         debug->len = lpfc_debugfs_hbqinfo_data(phba, debug->buffer,
617                 LPFC_HBQINFO_SIZE);
618         file->private_data = debug;
619
620         rc = 0;
621 out:
622         return rc;
623 }
624
625 static int
626 lpfc_debugfs_dumpslim_open(struct inode *inode, struct file *file)
627 {
628         struct lpfc_hba *phba = inode->i_private;
629         struct lpfc_debug *debug;
630         int rc = -ENOMEM;
631
632         debug = kmalloc(sizeof(*debug), GFP_KERNEL);
633         if (!debug)
634                 goto out;
635
636         /* Round to page boundry */
637         debug->buffer = kmalloc(LPFC_DUMPSLIM_SIZE, GFP_KERNEL);
638         if (!debug->buffer) {
639                 kfree(debug);
640                 goto out;
641         }
642
643         debug->len = lpfc_debugfs_dumpslim_data(phba, debug->buffer,
644                 LPFC_DUMPSLIM_SIZE);
645         file->private_data = debug;
646
647         rc = 0;
648 out:
649         return rc;
650 }
651
652 static int
653 lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file)
654 {
655         struct lpfc_vport *vport = inode->i_private;
656         struct lpfc_debug *debug;
657         int rc = -ENOMEM;
658
659         debug = kmalloc(sizeof(*debug), GFP_KERNEL);
660         if (!debug)
661                 goto out;
662
663         /* Round to page boundry */
664         debug->buffer = kmalloc(LPFC_NODELIST_SIZE, GFP_KERNEL);
665         if (!debug->buffer) {
666                 kfree(debug);
667                 goto out;
668         }
669
670         debug->len = lpfc_debugfs_nodelist_data(vport, debug->buffer,
671                 LPFC_NODELIST_SIZE);
672         file->private_data = debug;
673
674         rc = 0;
675 out:
676         return rc;
677 }
678
679 static loff_t
680 lpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
681 {
682         struct lpfc_debug *debug;
683         loff_t pos = -1;
684
685         debug = file->private_data;
686
687         switch (whence) {
688         case 0:
689                 pos = off;
690                 break;
691         case 1:
692                 pos = file->f_pos + off;
693                 break;
694         case 2:
695                 pos = debug->len - off;
696         }
697         return (pos < 0 || pos > debug->len) ? -EINVAL : (file->f_pos = pos);
698 }
699
700 static ssize_t
701 lpfc_debugfs_read(struct file *file, char __user *buf,
702                   size_t nbytes, loff_t *ppos)
703 {
704         struct lpfc_debug *debug = file->private_data;
705         return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer,
706                                        debug->len);
707 }
708
709 static int
710 lpfc_debugfs_release(struct inode *inode, struct file *file)
711 {
712         struct lpfc_debug *debug = file->private_data;
713
714         kfree(debug->buffer);
715         kfree(debug);
716
717         return 0;
718 }
719
720 #undef lpfc_debugfs_op_disc_trc
721 static struct file_operations lpfc_debugfs_op_disc_trc = {
722         .owner =        THIS_MODULE,
723         .open =         lpfc_debugfs_disc_trc_open,
724         .llseek =       lpfc_debugfs_lseek,
725         .read =         lpfc_debugfs_read,
726         .release =      lpfc_debugfs_release,
727 };
728
729 #undef lpfc_debugfs_op_nodelist
730 static struct file_operations lpfc_debugfs_op_nodelist = {
731         .owner =        THIS_MODULE,
732         .open =         lpfc_debugfs_nodelist_open,
733         .llseek =       lpfc_debugfs_lseek,
734         .read =         lpfc_debugfs_read,
735         .release =      lpfc_debugfs_release,
736 };
737
738 #undef lpfc_debugfs_op_hbqinfo
739 static struct file_operations lpfc_debugfs_op_hbqinfo = {
740         .owner =        THIS_MODULE,
741         .open =         lpfc_debugfs_hbqinfo_open,
742         .llseek =       lpfc_debugfs_lseek,
743         .read =         lpfc_debugfs_read,
744         .release =      lpfc_debugfs_release,
745 };
746
747 #undef lpfc_debugfs_op_dumpslim
748 static struct file_operations lpfc_debugfs_op_dumpslim = {
749         .owner =        THIS_MODULE,
750         .open =         lpfc_debugfs_dumpslim_open,
751         .llseek =       lpfc_debugfs_lseek,
752         .read =         lpfc_debugfs_read,
753         .release =      lpfc_debugfs_release,
754 };
755
756 #undef lpfc_debugfs_op_slow_ring_trc
757 static struct file_operations lpfc_debugfs_op_slow_ring_trc = {
758         .owner =        THIS_MODULE,
759         .open =         lpfc_debugfs_slow_ring_trc_open,
760         .llseek =       lpfc_debugfs_lseek,
761         .read =         lpfc_debugfs_read,
762         .release =      lpfc_debugfs_release,
763 };
764
765 static struct dentry *lpfc_debugfs_root = NULL;
766 static atomic_t lpfc_debugfs_hba_count;
767 #endif
768
769 inline void
770 lpfc_debugfs_initialize(struct lpfc_vport *vport)
771 {
772 #ifdef CONFIG_LPFC_DEBUG_FS
773         struct lpfc_hba   *phba = vport->phba;
774         char name[64];
775         uint32_t num, i;
776
777         if (!lpfc_debugfs_enable)
778                 return;
779
780         /* Setup lpfc root directory */
781         if (!lpfc_debugfs_root) {
782                 lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL);
783                 atomic_set(&lpfc_debugfs_hba_count, 0);
784                 if (!lpfc_debugfs_root) {
785                         lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
786                                          "0409 Cannot create debugfs root\n");
787                         goto debug_failed;
788                 }
789         }
790         if (!lpfc_debugfs_start_time)
791                 lpfc_debugfs_start_time = jiffies;
792
793         /* Setup lpfcX directory for specific HBA */
794         snprintf(name, sizeof(name), "lpfc%d", phba->brd_no);
795         if (!phba->hba_debugfs_root) {
796                 phba->hba_debugfs_root =
797                         debugfs_create_dir(name, lpfc_debugfs_root);
798                 if (!phba->hba_debugfs_root) {
799                         lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
800                                          "0409 Cannot create debugfs hba\n");
801                         goto debug_failed;
802                 }
803                 atomic_inc(&lpfc_debugfs_hba_count);
804                 atomic_set(&phba->debugfs_vport_count, 0);
805
806                 /* Setup hbqinfo */
807                 snprintf(name, sizeof(name), "hbqinfo");
808                 phba->debug_hbqinfo =
809                         debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
810                                  phba->hba_debugfs_root,
811                                  phba, &lpfc_debugfs_op_hbqinfo);
812                 if (!phba->debug_hbqinfo) {
813                         lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
814                                 "0409 Cannot create debugfs hbqinfo\n");
815                         goto debug_failed;
816                 }
817
818                 /* Setup dumpslim */
819                 snprintf(name, sizeof(name), "dumpslim");
820                 phba->debug_dumpslim =
821                         debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
822                                  phba->hba_debugfs_root,
823                                  phba, &lpfc_debugfs_op_dumpslim);
824                 if (!phba->debug_dumpslim) {
825                         lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
826                                 "0409 Cannot create debugfs dumpslim\n");
827                         goto debug_failed;
828                 }
829
830                 /* Setup slow ring trace */
831                 if (lpfc_debugfs_max_slow_ring_trc) {
832                         num = lpfc_debugfs_max_slow_ring_trc - 1;
833                         if (num & lpfc_debugfs_max_slow_ring_trc) {
834                                 /* Change to be a power of 2 */
835                                 num = lpfc_debugfs_max_slow_ring_trc;
836                                 i = 0;
837                                 while (num > 1) {
838                                         num = num >> 1;
839                                         i++;
840                                 }
841                                 lpfc_debugfs_max_slow_ring_trc = (1 << i);
842                                 printk(KERN_ERR
843                                        "lpfc_debugfs_max_disc_trc changed to "
844                                        "%d\n", lpfc_debugfs_max_disc_trc);
845                         }
846                 }
847
848
849                 snprintf(name, sizeof(name), "slow_ring_trace");
850                 phba->debug_slow_ring_trc =
851                         debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
852                                  phba->hba_debugfs_root,
853                                  phba, &lpfc_debugfs_op_slow_ring_trc);
854                 if (!phba->debug_slow_ring_trc) {
855                         lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
856                                          "0409 Cannot create debugfs "
857                                          "slow_ring_trace\n");
858                         goto debug_failed;
859                 }
860                 if (!phba->slow_ring_trc) {
861                         phba->slow_ring_trc = kmalloc(
862                                 (sizeof(struct lpfc_debugfs_trc) *
863                                 lpfc_debugfs_max_slow_ring_trc),
864                                 GFP_KERNEL);
865                         if (!phba->slow_ring_trc) {
866                                 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
867                                                  "0409 Cannot create debugfs "
868                                                  "slow_ring buffer\n");
869                                 goto debug_failed;
870                         }
871                         atomic_set(&phba->slow_ring_trc_cnt, 0);
872                         memset(phba->slow_ring_trc, 0,
873                                 (sizeof(struct lpfc_debugfs_trc) *
874                                 lpfc_debugfs_max_slow_ring_trc));
875                 }
876         }
877
878         snprintf(name, sizeof(name), "vport%d", vport->vpi);
879         if (!vport->vport_debugfs_root) {
880                 vport->vport_debugfs_root =
881                         debugfs_create_dir(name, phba->hba_debugfs_root);
882                 if (!vport->vport_debugfs_root) {
883                         lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
884                                          "0409 Cant create debugfs");
885                         goto debug_failed;
886                 }
887                 atomic_inc(&phba->debugfs_vport_count);
888         }
889
890         if (lpfc_debugfs_max_disc_trc) {
891                 num = lpfc_debugfs_max_disc_trc - 1;
892                 if (num & lpfc_debugfs_max_disc_trc) {
893                         /* Change to be a power of 2 */
894                         num = lpfc_debugfs_max_disc_trc;
895                         i = 0;
896                         while (num > 1) {
897                                 num = num >> 1;
898                                 i++;
899                         }
900                         lpfc_debugfs_max_disc_trc = (1 << i);
901                         printk(KERN_ERR
902                                "lpfc_debugfs_max_disc_trc changed to %d\n",
903                                lpfc_debugfs_max_disc_trc);
904                 }
905         }
906
907         vport->disc_trc = kmalloc(
908                 (sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc),
909                 GFP_KERNEL);
910
911         if (!vport->disc_trc) {
912                 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
913                                  "0409 Cannot create debugfs disc trace "
914                                  "buffer\n");
915                 goto debug_failed;
916         }
917         atomic_set(&vport->disc_trc_cnt, 0);
918         memset(vport->disc_trc, 0,
919                 (sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc));
920
921         snprintf(name, sizeof(name), "discovery_trace");
922         vport->debug_disc_trc =
923                 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
924                                  vport->vport_debugfs_root,
925                                  vport, &lpfc_debugfs_op_disc_trc);
926         if (!vport->debug_disc_trc) {
927                 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
928                                  "0409 Cannot create debugfs "
929                                  "discovery_trace\n");
930                 goto debug_failed;
931         }
932         snprintf(name, sizeof(name), "nodelist");
933         vport->debug_nodelist =
934                 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
935                                  vport->vport_debugfs_root,
936                                  vport, &lpfc_debugfs_op_nodelist);
937         if (!vport->debug_nodelist) {
938                 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
939                                  "0409 Cant create debugfs nodelist");
940                 goto debug_failed;
941         }
942 debug_failed:
943         return;
944 #endif
945 }
946
947
948 inline void
949 lpfc_debugfs_terminate(struct lpfc_vport *vport)
950 {
951 #ifdef CONFIG_LPFC_DEBUG_FS
952         struct lpfc_hba   *phba = vport->phba;
953
954         if (vport->disc_trc) {
955                 kfree(vport->disc_trc);
956                 vport->disc_trc = NULL;
957         }
958         if (vport->debug_disc_trc) {
959                 debugfs_remove(vport->debug_disc_trc); /* discovery_trace */
960                 vport->debug_disc_trc = NULL;
961         }
962         if (vport->debug_nodelist) {
963                 debugfs_remove(vport->debug_nodelist); /* nodelist */
964                 vport->debug_nodelist = NULL;
965         }
966
967         if (vport->vport_debugfs_root) {
968                 debugfs_remove(vport->vport_debugfs_root); /* vportX */
969                 vport->vport_debugfs_root = NULL;
970                 atomic_dec(&phba->debugfs_vport_count);
971         }
972         if (atomic_read(&phba->debugfs_vport_count) == 0) {
973
974                 if (phba->debug_hbqinfo) {
975                         debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */
976                         phba->debug_hbqinfo = NULL;
977                 }
978                 if (phba->debug_dumpslim) {
979                         debugfs_remove(phba->debug_dumpslim); /* dumpslim */
980                         phba->debug_dumpslim = NULL;
981                 }
982                 if (phba->slow_ring_trc) {
983                         kfree(phba->slow_ring_trc);
984                         phba->slow_ring_trc = NULL;
985                 }
986                 if (phba->debug_slow_ring_trc) {
987                         /* slow_ring_trace */
988                         debugfs_remove(phba->debug_slow_ring_trc);
989                         phba->debug_slow_ring_trc = NULL;
990                 }
991
992                 if (phba->hba_debugfs_root) {
993                         debugfs_remove(phba->hba_debugfs_root); /* lpfcX */
994                         phba->hba_debugfs_root = NULL;
995                         atomic_dec(&lpfc_debugfs_hba_count);
996                 }
997
998                 if (atomic_read(&lpfc_debugfs_hba_count) == 0) {
999                         debugfs_remove(lpfc_debugfs_root); /* lpfc */
1000                         lpfc_debugfs_root = NULL;
1001                 }
1002         }
1003 #endif
1004         return;
1005 }
1006
1007