2 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License (GPL) Version 2 as
10 * published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
18 #include <linux/debugfs.h>
24 * BFA debufs interface
26 * To access the interface, debugfs file system should be mounted
27 * if not already mounted using:
28 * mount -t debugfs none /sys/kernel/debug
32 * where the host number corresponds to the one under /sys/class/scsi_host/host#
34 * Debugging service available per host:
35 * fwtrc: To collect current firmware trace.
36 * drvtrc: To collect current driver trace
37 * fwsave: To collect last saved fw trace as a result of firmware crash.
38 * regwr: To write one word to chip register
39 * regrd: To read one or more words from chip register.
42 struct bfad_debug_info
{
49 bfad_debugfs_open_drvtrc(struct inode
*inode
, struct file
*file
)
51 struct bfad_port_s
*port
= inode
->i_private
;
52 struct bfad_s
*bfad
= port
->bfad
;
53 struct bfad_debug_info
*debug
;
55 debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
59 debug
->debug_buffer
= (void *) bfad
->trcmod
;
60 debug
->buffer_len
= sizeof(struct bfa_trc_mod_s
);
62 file
->private_data
= debug
;
68 bfad_debugfs_open_fwtrc(struct inode
*inode
, struct file
*file
)
70 struct bfad_port_s
*port
= inode
->i_private
;
71 struct bfad_s
*bfad
= port
->bfad
;
72 struct bfad_debug_info
*fw_debug
;
76 fw_debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
80 fw_debug
->buffer_len
= sizeof(struct bfa_trc_mod_s
);
82 fw_debug
->debug_buffer
= vmalloc(fw_debug
->buffer_len
);
83 if (!fw_debug
->debug_buffer
) {
85 printk(KERN_INFO
"bfad[%d]: Failed to allocate fwtrc buffer\n",
90 memset(fw_debug
->debug_buffer
, 0, fw_debug
->buffer_len
);
92 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
93 rc
= bfa_debug_fwtrc(&bfad
->bfa
,
94 fw_debug
->debug_buffer
,
95 &fw_debug
->buffer_len
);
96 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
97 if (rc
!= BFA_STATUS_OK
) {
98 vfree(fw_debug
->debug_buffer
);
99 fw_debug
->debug_buffer
= NULL
;
101 printk(KERN_INFO
"bfad[%d]: Failed to collect fwtrc\n",
106 file
->private_data
= fw_debug
;
112 bfad_debugfs_open_fwsave(struct inode
*inode
, struct file
*file
)
114 struct bfad_port_s
*port
= inode
->i_private
;
115 struct bfad_s
*bfad
= port
->bfad
;
116 struct bfad_debug_info
*fw_debug
;
120 fw_debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
124 fw_debug
->buffer_len
= sizeof(struct bfa_trc_mod_s
);
126 fw_debug
->debug_buffer
= vmalloc(fw_debug
->buffer_len
);
127 if (!fw_debug
->debug_buffer
) {
129 printk(KERN_INFO
"bfad[%d]: Failed to allocate fwsave buffer\n",
134 memset(fw_debug
->debug_buffer
, 0, fw_debug
->buffer_len
);
136 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
137 rc
= bfa_debug_fwsave(&bfad
->bfa
,
138 fw_debug
->debug_buffer
,
139 &fw_debug
->buffer_len
);
140 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
141 if (rc
!= BFA_STATUS_OK
) {
142 vfree(fw_debug
->debug_buffer
);
143 fw_debug
->debug_buffer
= NULL
;
145 printk(KERN_INFO
"bfad[%d]: Failed to collect fwsave\n",
150 file
->private_data
= fw_debug
;
156 bfad_debugfs_open_reg(struct inode
*inode
, struct file
*file
)
158 struct bfad_debug_info
*reg_debug
;
160 reg_debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
164 reg_debug
->i_private
= inode
->i_private
;
166 file
->private_data
= reg_debug
;
171 /* Changes the current file position */
173 bfad_debugfs_lseek(struct file
*file
, loff_t offset
, int orig
)
175 struct bfad_debug_info
*debug
;
176 loff_t pos
= file
->f_pos
;
178 debug
= file
->private_data
;
182 file
->f_pos
= offset
;
185 file
->f_pos
+= offset
;
188 file
->f_pos
= debug
->buffer_len
- offset
;
194 if (file
->f_pos
< 0 || file
->f_pos
> debug
->buffer_len
) {
203 bfad_debugfs_read(struct file
*file
, char __user
*buf
,
204 size_t nbytes
, loff_t
*pos
)
206 struct bfad_debug_info
*debug
= file
->private_data
;
208 if (!debug
|| !debug
->debug_buffer
)
211 return memory_read_from_buffer(buf
, nbytes
, pos
,
212 debug
->debug_buffer
, debug
->buffer_len
);
215 #define BFA_REG_CT_ADDRSZ (0x40000)
216 #define BFA_REG_CB_ADDRSZ (0x20000)
217 #define BFA_REG_ADDRSZ(__bfa) \
218 ((bfa_ioc_devid(&(__bfa)->ioc) == BFA_PCI_DEVICE_ID_CT) ? \
219 BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ)
220 #define BFA_REG_ADDRMSK(__bfa) ((uint32_t)(BFA_REG_ADDRSZ(__bfa) - 1))
223 bfad_reg_offset_check(struct bfa_s
*bfa
, u32 offset
, u32 len
)
228 area
= (offset
>> 15) & 0x7;
230 /* PCIe core register */
231 if ((offset
+ (len
<<2)) > 0x8000) /* 8k dwords or 32KB */
232 return BFA_STATUS_EINVAL
;
233 } else if (area
== 0x1) {
234 /* CB 32 KB memory page */
235 if ((offset
+ (len
<<2)) > 0x10000) /* 8k dwords or 32KB */
236 return BFA_STATUS_EINVAL
;
238 /* CB register space 64KB */
239 if ((offset
+ (len
<<2)) > BFA_REG_ADDRMSK(bfa
))
240 return BFA_STATUS_EINVAL
;
242 return BFA_STATUS_OK
;
246 bfad_debugfs_read_regrd(struct file
*file
, char __user
*buf
,
247 size_t nbytes
, loff_t
*pos
)
249 struct bfad_debug_info
*regrd_debug
= file
->private_data
;
250 struct bfad_port_s
*port
= (struct bfad_port_s
*)regrd_debug
->i_private
;
251 struct bfad_s
*bfad
= port
->bfad
;
257 rc
= memory_read_from_buffer(buf
, nbytes
, pos
,
258 bfad
->regdata
, bfad
->reglen
);
260 if ((*pos
+ nbytes
) >= bfad
->reglen
) {
261 kfree(bfad
->regdata
);
262 bfad
->regdata
= NULL
;
270 bfad_debugfs_write_regrd(struct file
*file
, const char __user
*buf
,
271 size_t nbytes
, loff_t
*ppos
)
273 struct bfad_debug_info
*regrd_debug
= file
->private_data
;
274 struct bfad_port_s
*port
= (struct bfad_port_s
*)regrd_debug
->i_private
;
275 struct bfad_s
*bfad
= port
->bfad
;
276 struct bfa_s
*bfa
= &bfad
->bfa
;
277 struct bfa_ioc_s
*ioc
= &bfa
->ioc
;
278 int addr
, len
, rc
, i
;
280 void __iomem
*rb
, *reg_addr
;
283 rc
= sscanf(buf
, "%x:%x", &addr
, &len
);
286 "bfad[%d]: %s failed to read user buf\n",
287 bfad
->inst_no
, __func__
);
291 kfree(bfad
->regdata
);
292 bfad
->regdata
= NULL
;
295 bfad
->regdata
= kzalloc(len
<< 2, GFP_KERNEL
);
296 if (!bfad
->regdata
) {
297 printk(KERN_INFO
"bfad[%d]: Failed to allocate regrd buffer\n",
302 bfad
->reglen
= len
<< 2;
303 rb
= bfa_ioc_bar0(ioc
);
304 addr
&= BFA_REG_ADDRMSK(bfa
);
306 /* offset and len sanity check */
307 rc
= bfad_reg_offset_check(bfa
, addr
, len
);
309 printk(KERN_INFO
"bfad[%d]: Failed reg offset check\n",
311 kfree(bfad
->regdata
);
312 bfad
->regdata
= NULL
;
317 reg_addr
= rb
+ addr
;
318 regbuf
= (u32
*)bfad
->regdata
;
319 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
320 for (i
= 0; i
< len
; i
++) {
321 *regbuf
= bfa_reg_read(reg_addr
);
323 reg_addr
+= sizeof(u32
);
325 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
331 bfad_debugfs_write_regwr(struct file
*file
, const char __user
*buf
,
332 size_t nbytes
, loff_t
*ppos
)
334 struct bfad_debug_info
*debug
= file
->private_data
;
335 struct bfad_port_s
*port
= (struct bfad_port_s
*)debug
->i_private
;
336 struct bfad_s
*bfad
= port
->bfad
;
337 struct bfa_s
*bfa
= &bfad
->bfa
;
338 struct bfa_ioc_s
*ioc
= &bfa
->ioc
;
340 void __iomem
*reg_addr
;
343 rc
= sscanf(buf
, "%x:%x", &addr
, &val
);
346 "bfad[%d]: %s failed to read user buf\n",
347 bfad
->inst_no
, __func__
);
351 addr
&= BFA_REG_ADDRMSK(bfa
); /* offset only 17 bit and word align */
353 /* offset and len sanity check */
354 rc
= bfad_reg_offset_check(bfa
, addr
, 1);
357 "bfad[%d]: Failed reg offset check\n",
362 reg_addr
= (uint32_t *) ((uint8_t *) bfa_ioc_bar0(ioc
) + addr
);
363 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
364 bfa_reg_write(reg_addr
, val
);
365 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
371 bfad_debugfs_release(struct inode
*inode
, struct file
*file
)
373 struct bfad_debug_info
*debug
= file
->private_data
;
378 file
->private_data
= NULL
;
384 bfad_debugfs_release_fwtrc(struct inode
*inode
, struct file
*file
)
386 struct bfad_debug_info
*fw_debug
= file
->private_data
;
391 if (fw_debug
->debug_buffer
)
392 vfree(fw_debug
->debug_buffer
);
394 file
->private_data
= NULL
;
399 static const struct file_operations bfad_debugfs_op_drvtrc
= {
400 .owner
= THIS_MODULE
,
401 .open
= bfad_debugfs_open_drvtrc
,
402 .llseek
= bfad_debugfs_lseek
,
403 .read
= bfad_debugfs_read
,
404 .release
= bfad_debugfs_release
,
407 static const struct file_operations bfad_debugfs_op_fwtrc
= {
408 .owner
= THIS_MODULE
,
409 .open
= bfad_debugfs_open_fwtrc
,
410 .llseek
= bfad_debugfs_lseek
,
411 .read
= bfad_debugfs_read
,
412 .release
= bfad_debugfs_release_fwtrc
,
415 static const struct file_operations bfad_debugfs_op_fwsave
= {
416 .owner
= THIS_MODULE
,
417 .open
= bfad_debugfs_open_fwsave
,
418 .llseek
= bfad_debugfs_lseek
,
419 .read
= bfad_debugfs_read
,
420 .release
= bfad_debugfs_release_fwtrc
,
423 static const struct file_operations bfad_debugfs_op_regrd
= {
424 .owner
= THIS_MODULE
,
425 .open
= bfad_debugfs_open_reg
,
426 .llseek
= bfad_debugfs_lseek
,
427 .read
= bfad_debugfs_read_regrd
,
428 .write
= bfad_debugfs_write_regrd
,
429 .release
= bfad_debugfs_release
,
432 static const struct file_operations bfad_debugfs_op_regwr
= {
433 .owner
= THIS_MODULE
,
434 .open
= bfad_debugfs_open_reg
,
435 .llseek
= bfad_debugfs_lseek
,
436 .write
= bfad_debugfs_write_regwr
,
437 .release
= bfad_debugfs_release
,
440 struct bfad_debugfs_entry
{
443 const struct file_operations
*fops
;
446 static const struct bfad_debugfs_entry bfad_debugfs_files
[] = {
447 { "drvtrc", S_IFREG
|S_IRUGO
, &bfad_debugfs_op_drvtrc
, },
448 { "fwtrc", S_IFREG
|S_IRUGO
, &bfad_debugfs_op_fwtrc
, },
449 { "fwsave", S_IFREG
|S_IRUGO
, &bfad_debugfs_op_fwsave
, },
450 { "regrd", S_IFREG
|S_IRUGO
|S_IWUSR
, &bfad_debugfs_op_regrd
, },
451 { "regwr", S_IFREG
|S_IWUSR
, &bfad_debugfs_op_regwr
, },
454 static struct dentry
*bfa_debugfs_root
;
455 static atomic_t bfa_debugfs_port_count
;
458 bfad_debugfs_init(struct bfad_port_s
*port
)
460 struct bfad_im_port_s
*im_port
= port
->im_port
;
461 struct bfad_s
*bfad
= im_port
->bfad
;
462 struct Scsi_Host
*shost
= im_port
->shost
;
463 const struct bfad_debugfs_entry
*file
;
467 if (!bfa_debugfs_enable
)
470 /* Setup the BFA debugfs root directory*/
471 if (!bfa_debugfs_root
) {
472 bfa_debugfs_root
= debugfs_create_dir("bfa", NULL
);
473 atomic_set(&bfa_debugfs_port_count
, 0);
474 if (!bfa_debugfs_root
) {
476 "BFA debugfs root dir creation failed\n");
482 * Setup the host# directory for the port,
483 * corresponds to the scsi_host num of this port.
485 snprintf(name
, sizeof(name
), "host%d", shost
->host_no
);
486 if (!port
->port_debugfs_root
) {
487 port
->port_debugfs_root
=
488 debugfs_create_dir(name
, bfa_debugfs_root
);
489 if (!port
->port_debugfs_root
) {
491 "BFA host root dir creation failed\n");
495 atomic_inc(&bfa_debugfs_port_count
);
497 for (i
= 0; i
< ARRAY_SIZE(bfad_debugfs_files
); i
++) {
498 file
= &bfad_debugfs_files
[i
];
499 bfad
->bfad_dentry_files
[i
] =
500 debugfs_create_file(file
->name
,
502 port
->port_debugfs_root
,
505 if (!bfad
->bfad_dentry_files
[i
]) {
507 "BFA host%d: create %s entry failed\n",
508 shost
->host_no
, file
->name
);
519 bfad_debugfs_exit(struct bfad_port_s
*port
)
521 struct bfad_im_port_s
*im_port
= port
->im_port
;
522 struct bfad_s
*bfad
= im_port
->bfad
;
525 for (i
= 0; i
< ARRAY_SIZE(bfad_debugfs_files
); i
++) {
526 if (bfad
->bfad_dentry_files
[i
]) {
527 debugfs_remove(bfad
->bfad_dentry_files
[i
]);
528 bfad
->bfad_dentry_files
[i
] = NULL
;
533 * Remove the host# directory for the port,
534 * corresponds to the scsi_host num of this port.
536 if (port
->port_debugfs_root
) {
537 debugfs_remove(port
->port_debugfs_root
);
538 port
->port_debugfs_root
= NULL
;
539 atomic_dec(&bfa_debugfs_port_count
);
542 /* Remove the BFA debugfs root directory */
543 if (atomic_read(&bfa_debugfs_port_count
) == 0) {
544 debugfs_remove(bfa_debugfs_root
);
545 bfa_debugfs_root
= NULL
;