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