xref: /linux/drivers/scsi/lpfc/lpfc_debugfs.c (revision 8b4a40809e5330c9da5d20107d693d92d73b31dc)
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 static int lpfc_debugfs_max_disc_trc = 0;  /* This MUST be a power of 2 */
79 module_param(lpfc_debugfs_max_disc_trc, int, 0);
80 MODULE_PARM_DESC(lpfc_debugfs_max_disc_trc,
81 	"Set debugfs discovery trace depth");
82 
83 static int lpfc_debugfs_mask_disc_trc = 0;
84 module_param(lpfc_debugfs_mask_disc_trc, int, 0);
85 MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc,
86 	"Set debugfs discovery trace mask");
87 
88 #include <linux/debugfs.h>
89 
90 /* size of discovery_trace output line */
91 #define LPFC_DISC_TRC_ENTRY_SIZE 80
92 
93 /* nodelist output buffer size */
94 #define LPFC_NODELIST_SIZE 8192
95 #define LPFC_NODELIST_ENTRY_SIZE 120
96 
97 struct lpfc_debug {
98 	char *buffer;
99 	int  len;
100 };
101 
102 atomic_t lpfc_debugfs_disc_trc_cnt = ATOMIC_INIT(0);
103 unsigned long lpfc_debugfs_start_time = 0L;
104 
105 static int
106 lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
107 {
108 	int i, index, len, enable;
109 	uint32_t ms;
110 	struct lpfc_disc_trc *dtp;
111 	char buffer[80];
112 
113 
114 	enable = lpfc_debugfs_enable;
115 	lpfc_debugfs_enable = 0;
116 
117 	len = 0;
118 	index = (atomic_read(&vport->disc_trc_cnt) + 1) &
119 		(lpfc_debugfs_max_disc_trc - 1);
120 	for (i = index; i < lpfc_debugfs_max_disc_trc; i++) {
121 		dtp = vport->disc_trc + i;
122 		if (!dtp->fmt)
123 			continue;
124 		ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
125 		snprintf(buffer, 80, "%010d:%010d ms:%s\n",
126 			dtp->seq_cnt, ms, dtp->fmt);
127 		len +=  snprintf(buf+len, size-len, buffer,
128 			dtp->data1, dtp->data2, dtp->data3);
129 	}
130 	for (i = 0; i < index; i++) {
131 		dtp = vport->disc_trc + i;
132 		if (!dtp->fmt)
133 			continue;
134 		ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
135 		snprintf(buffer, 80, "%010d:%010d ms:%s\n",
136 			dtp->seq_cnt, ms, dtp->fmt);
137 		len +=  snprintf(buf+len, size-len, buffer,
138 			dtp->data1, dtp->data2, dtp->data3);
139 	}
140 
141 	lpfc_debugfs_enable = enable;
142 	return len;
143 }
144 
145 static int
146 lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
147 {
148 	int len = 0;
149 	int cnt;
150 	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
151 	struct lpfc_nodelist *ndlp;
152 	unsigned char *statep, *name;
153 
154 	cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
155 
156 	spin_lock_irq(shost->host_lock);
157 	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
158 		if (!cnt) {
159 			len +=  snprintf(buf+len, size-len,
160 				"Missing Nodelist Entries\n");
161 			break;
162 		}
163 		cnt--;
164 		switch (ndlp->nlp_state) {
165 		case NLP_STE_UNUSED_NODE:
166 			statep = "UNUSED";
167 			break;
168 		case NLP_STE_PLOGI_ISSUE:
169 			statep = "PLOGI ";
170 			break;
171 		case NLP_STE_ADISC_ISSUE:
172 			statep = "ADISC ";
173 			break;
174 		case NLP_STE_REG_LOGIN_ISSUE:
175 			statep = "REGLOG";
176 			break;
177 		case NLP_STE_PRLI_ISSUE:
178 			statep = "PRLI  ";
179 			break;
180 		case NLP_STE_UNMAPPED_NODE:
181 			statep = "UNMAP ";
182 			break;
183 		case NLP_STE_MAPPED_NODE:
184 			statep = "MAPPED";
185 			break;
186 		case NLP_STE_NPR_NODE:
187 			statep = "NPR   ";
188 			break;
189 		default:
190 			statep = "UNKNOWN";
191 		}
192 		len +=  snprintf(buf+len, size-len, "%s DID:x%06x ",
193 			statep, ndlp->nlp_DID);
194 		name = (unsigned char *)&ndlp->nlp_portname;
195 		len +=  snprintf(buf+len, size-len,
196 			"WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",
197 			*name, *(name+1), *(name+2), *(name+3),
198 			*(name+4), *(name+5), *(name+6), *(name+7));
199 		name = (unsigned char *)&ndlp->nlp_nodename;
200 		len +=  snprintf(buf+len, size-len,
201 			"WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",
202 			*name, *(name+1), *(name+2), *(name+3),
203 			*(name+4), *(name+5), *(name+6), *(name+7));
204 		len +=  snprintf(buf+len, size-len, "RPI:%03d flag:x%08x ",
205 			ndlp->nlp_rpi, ndlp->nlp_flag);
206 		if (!ndlp->nlp_type)
207 			len +=  snprintf(buf+len, size-len, "UNKNOWN_TYPE");
208 		if (ndlp->nlp_type & NLP_FC_NODE)
209 			len +=  snprintf(buf+len, size-len, "FC_NODE ");
210 		if (ndlp->nlp_type & NLP_FABRIC)
211 			len +=  snprintf(buf+len, size-len, "FABRIC ");
212 		if (ndlp->nlp_type & NLP_FCP_TARGET)
213 			len +=  snprintf(buf+len, size-len, "FCP_TGT sid:%d ",
214 				ndlp->nlp_sid);
215 		if (ndlp->nlp_type & NLP_FCP_INITIATOR)
216 			len +=  snprintf(buf+len, size-len, "FCP_INITIATOR");
217 		len +=  snprintf(buf+len, size-len, "\n");
218 	}
219 	spin_unlock_irq(shost->host_lock);
220 	return len;
221 }
222 #endif
223 
224 
225 inline void
226 lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt,
227 	uint32_t data1, uint32_t data2, uint32_t data3)
228 {
229 #ifdef CONFIG_LPFC_DEBUG_FS
230 	struct lpfc_disc_trc *dtp;
231 	int index;
232 
233 	if (!(lpfc_debugfs_mask_disc_trc & mask))
234 		return;
235 
236 	if (!lpfc_debugfs_enable || !lpfc_debugfs_max_disc_trc ||
237 		!vport || !vport->disc_trc)
238 		return;
239 
240 	index = atomic_inc_return(&vport->disc_trc_cnt) &
241 		(lpfc_debugfs_max_disc_trc - 1);
242 	dtp = vport->disc_trc + index;
243 	dtp->fmt = fmt;
244 	dtp->data1 = data1;
245 	dtp->data2 = data2;
246 	dtp->data3 = data3;
247 	dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_disc_trc_cnt);
248 	dtp->jif = jiffies;
249 #endif
250 	return;
251 }
252 
253 #ifdef CONFIG_LPFC_DEBUG_FS
254 static int
255 lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file)
256 {
257 	struct lpfc_vport *vport = inode->i_private;
258 	struct lpfc_debug *debug;
259 	int size;
260 	int rc = -ENOMEM;
261 
262 	if (!lpfc_debugfs_max_disc_trc) {
263 		 rc = -ENOSPC;
264 		goto out;
265 	}
266 
267 	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
268 	if (!debug)
269 		goto out;
270 
271 	/* Round to page boundry */
272 	size =  (lpfc_debugfs_max_disc_trc * LPFC_DISC_TRC_ENTRY_SIZE);
273 	size = PAGE_ALIGN(size);
274 
275 	debug->buffer = kmalloc(size, GFP_KERNEL);
276 	if (!debug->buffer) {
277 		kfree(debug);
278 		goto out;
279 	}
280 
281 	debug->len = lpfc_debugfs_disc_trc_data(vport, debug->buffer, size);
282 	file->private_data = debug;
283 
284 	rc = 0;
285 out:
286 	return rc;
287 }
288 
289 static int
290 lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file)
291 {
292 	struct lpfc_vport *vport = inode->i_private;
293 	struct lpfc_debug *debug;
294 	int rc = -ENOMEM;
295 
296 	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
297 	if (!debug)
298 		goto out;
299 
300 	/* Round to page boundry */
301 	debug->buffer = kmalloc(LPFC_NODELIST_SIZE, GFP_KERNEL);
302 	if (!debug->buffer) {
303 		kfree(debug);
304 		goto out;
305 	}
306 
307 	debug->len = lpfc_debugfs_nodelist_data(vport, debug->buffer,
308 		LPFC_NODELIST_SIZE);
309 	file->private_data = debug;
310 
311 	rc = 0;
312 out:
313 	return rc;
314 }
315 
316 static loff_t
317 lpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
318 {
319 	struct lpfc_debug *debug;
320 	loff_t pos = -1;
321 
322 	debug = file->private_data;
323 
324 	switch (whence) {
325 	case 0:
326 		pos = off;
327 		break;
328 	case 1:
329 		pos = file->f_pos + off;
330 		break;
331 	case 2:
332 		pos = debug->len - off;
333 	}
334 	return (pos < 0 || pos > debug->len) ? -EINVAL : (file->f_pos = pos);
335 }
336 
337 static ssize_t
338 lpfc_debugfs_read(struct file *file, char __user *buf,
339 		  size_t nbytes, loff_t *ppos)
340 {
341 	struct lpfc_debug *debug = file->private_data;
342 	return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer,
343 				       debug->len);
344 }
345 
346 static int
347 lpfc_debugfs_release(struct inode *inode, struct file *file)
348 {
349 	struct lpfc_debug *debug = file->private_data;
350 
351 	kfree(debug->buffer);
352 	kfree(debug);
353 
354 	return 0;
355 }
356 
357 #undef lpfc_debugfs_op_disc_trc
358 static struct file_operations lpfc_debugfs_op_disc_trc = {
359 	.owner =        THIS_MODULE,
360 	.open =         lpfc_debugfs_disc_trc_open,
361 	.llseek =       lpfc_debugfs_lseek,
362 	.read =         lpfc_debugfs_read,
363 	.release =      lpfc_debugfs_release,
364 };
365 
366 #undef lpfc_debugfs_op_nodelist
367 static struct file_operations lpfc_debugfs_op_nodelist = {
368 	.owner =        THIS_MODULE,
369 	.open =         lpfc_debugfs_nodelist_open,
370 	.llseek =       lpfc_debugfs_lseek,
371 	.read =         lpfc_debugfs_read,
372 	.release =      lpfc_debugfs_release,
373 };
374 
375 static struct dentry *lpfc_debugfs_root = NULL;
376 static atomic_t lpfc_debugfs_hba_count;
377 #endif
378 
379 inline void
380 lpfc_debugfs_initialize(struct lpfc_vport *vport)
381 {
382 #ifdef CONFIG_LPFC_DEBUG_FS
383 	struct lpfc_hba   *phba = vport->phba;
384 	char name[64];
385 	uint32_t num, i;
386 
387 	if (!lpfc_debugfs_enable)
388 		return;
389 
390 	if (lpfc_debugfs_max_disc_trc) {
391 		num = lpfc_debugfs_max_disc_trc - 1;
392 		if (num & lpfc_debugfs_max_disc_trc) {
393 			/* Change to be a power of 2 */
394 			num = lpfc_debugfs_max_disc_trc;
395 			i = 0;
396 			while (num > 1) {
397 				num = num >> 1;
398 				i++;
399 			}
400 			lpfc_debugfs_max_disc_trc = (1 << i);
401 			printk(KERN_ERR
402 				"lpfc_debugfs_max_disc_trc changed to %d\n",
403 				lpfc_debugfs_max_disc_trc);
404 		}
405 	}
406 
407 	if (!lpfc_debugfs_root) {
408 		lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL);
409 		atomic_set(&lpfc_debugfs_hba_count, 0);
410 		if (!lpfc_debugfs_root)
411 			goto debug_failed;
412 	}
413 
414 	snprintf(name, sizeof(name), "lpfc%d", phba->brd_no);
415 	if (!phba->hba_debugfs_root) {
416 		phba->hba_debugfs_root =
417 			debugfs_create_dir(name, lpfc_debugfs_root);
418 		if (!phba->hba_debugfs_root)
419 			goto debug_failed;
420 		atomic_inc(&lpfc_debugfs_hba_count);
421 		atomic_set(&phba->debugfs_vport_count, 0);
422 	}
423 
424 	snprintf(name, sizeof(name), "vport%d", vport->vpi);
425 	if (!vport->vport_debugfs_root) {
426 		vport->vport_debugfs_root =
427 			debugfs_create_dir(name, phba->hba_debugfs_root);
428 		if (!vport->vport_debugfs_root)
429 			goto debug_failed;
430 		atomic_inc(&phba->debugfs_vport_count);
431 	}
432 
433 	if (!lpfc_debugfs_start_time)
434 		lpfc_debugfs_start_time = jiffies;
435 
436 	vport->disc_trc = kmalloc(
437 		(sizeof(struct lpfc_disc_trc) * lpfc_debugfs_max_disc_trc),
438 		GFP_KERNEL);
439 
440 	if (!vport->disc_trc)
441 		goto debug_failed;
442 	memset(vport->disc_trc, 0,
443 		(sizeof(struct lpfc_disc_trc) * lpfc_debugfs_max_disc_trc));
444 
445 	snprintf(name, sizeof(name), "discovery_trace");
446 	vport->debug_disc_trc =
447 		debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
448 				 vport->vport_debugfs_root,
449 				 vport, &lpfc_debugfs_op_disc_trc);
450 	if (!vport->debug_disc_trc) {
451 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
452 				"%d:0409 Cannot create debugfs",
453 				phba->brd_no);
454 		goto debug_failed;
455 	}
456 	snprintf(name, sizeof(name), "nodelist");
457 	vport->debug_nodelist =
458 		debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
459 				 vport->vport_debugfs_root,
460 				 vport, &lpfc_debugfs_op_nodelist);
461 	if (!vport->debug_nodelist) {
462 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
463 				"%d:0409 Cannot create debugfs",
464 				phba->brd_no);
465 		goto debug_failed;
466 	}
467 debug_failed:
468 	return;
469 #endif
470 }
471 
472 
473 inline void
474 lpfc_debugfs_terminate(struct lpfc_vport *vport)
475 {
476 #ifdef CONFIG_LPFC_DEBUG_FS
477 	struct lpfc_hba   *phba = vport->phba;
478 
479 	if (vport->disc_trc) {
480 		kfree(vport->disc_trc);
481 		vport->disc_trc = NULL;
482 	}
483 	if (vport->debug_disc_trc) {
484 		debugfs_remove(vport->debug_disc_trc); /* discovery_trace */
485 		vport->debug_disc_trc = NULL;
486 	}
487 	if (vport->debug_nodelist) {
488 		debugfs_remove(vport->debug_nodelist); /* nodelist */
489 		vport->debug_nodelist = NULL;
490 	}
491 	if (vport->vport_debugfs_root) {
492 		debugfs_remove(vport->vport_debugfs_root); /* vportX */
493 		vport->vport_debugfs_root = NULL;
494 		atomic_dec(&phba->debugfs_vport_count);
495 	}
496 	if (atomic_read(&phba->debugfs_vport_count) == 0) {
497 		debugfs_remove(vport->phba->hba_debugfs_root); /* lpfcX */
498 		vport->phba->hba_debugfs_root = NULL;
499 		atomic_dec(&lpfc_debugfs_hba_count);
500 		if (atomic_read(&lpfc_debugfs_hba_count) == 0) {
501 			debugfs_remove(lpfc_debugfs_root); /* lpfc */
502 			lpfc_debugfs_root = NULL;
503 		}
504 	}
505 #endif
506 }
507 
508 
509